P3002 [USACO10DEC]恐吓信Threatening Letter

题目描述

FJ has had a terrible fight with his neighbor and wants to send him a nasty letter, but wants to remain anonymous. As so many before him have done, he plans to cut out printed letters and paste them onto a sheet of paper. He has an infinite number of the most recent issue of the Moo York Times that has N (1 <= N <= 50,000) uppercase letters laid out in a long string (though read in as a series of shorter strings). Likewise, he has a message he'd like to compose that is a single long string of letters but that is read in as a set of shorter strings.

Being lazy, he wants to make the smallest possible number of cuts. FJ has a really great set of scissors that enables him to remove any single-line snippet from the Moo York Times with one cut. He notices that he can cut entire words or phrases with a single cut, thus reducing his total number of cuts.

What is the minimum amount of cuts he has to make to construct his letter of M (1 <= M <= 50,000) letters?

It is guaranteed that it is possible for FJ to complete his task.

Consider a 38 letter Moo York Times:

THEQUICKBROWNFOXDO 
GJUMPSOVERTHELAZYDOG 
from which FJ wants to construct a 9 letter message: 
FOXDOG 
DOG 

These input lines represent a pair of strings: THEQUICKBROWNFOXDOGJUMPSOVERTHELAZYDOG

FOXDOGDOG

Since 'FOXDOG' exists in the newspaper, FJ can cut this piece out and then get the last 'DOG' by cutting out either instance of the word 'DOG'.

Thus, he requires but two cuts.

FJ刚刚和邻居发生了一场可怕的争吵,他咽不下这口气,决定佚名发给他的邻居 一封脏话连篇的信。他有无限张完全相同的已经打印好的信件,都包含 N个字母(1 <= N <= 50,000)。他想剪出其中一些并且粘帖成一个很长的字母串。 FJ太懒了,他想用最少的次数裁剪信件。他有一把举世无双的剪刀,他可以从 一封信中只剪一刀剪出连续一段。同样,剪一刀可以得到整个完整的字符串。 他想知道他最少需要剪多少刀从而获得这封M个字母的长信? 保证这总是可能的。

输入格式

* Line 1: Two space-separated integers: N and M

* Lines 2..?: N letters laid out on several input lines; this is the text of the one copy of the Moo York Times. Each line will have no more than 80 characters.

* Lines ?..?: M letters that are the text of FJ's letter. Each line will have no more than 80 characters.

输出格式

* Line 1: The minimum number of cuts FJ has to make to create his message

输入输出样例

输入 #1
38 9 

THEQUICKBROWNFOXDO 

GJUMPSOVERTHELAZYDOG 

FOXDOG 

DOG 

输出 #1
2

思路

对串S建SAM,然后在上面尽可能地匹配T,匹配几次得到T就是答案

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=100010;

int tot,last,n,m,b[N];

struct no{
	int len,fa,t[30];
} t[2*N];

void insert(int c) {
	int np=++tot;
	t[np].len=t[last].len+1;
	int x=last;
	while(x&&!t[x].t[c]) {
		t[x].t[c]=np;
		x=t[x].fa;
	}
	last=np;
	if(!x)
		t[np].fa=1;
	else {
		int y=t[x].t[c];
		if(t[y].len==t[x].len+1)
			t[np].fa=y;
		else {
			int nq=++tot;
			t[nq]=t[y];
			t[nq].len=t[x].len+1;
			t[nq].fa=t[y].fa;
			t[y].fa=t[np].fa=nq;
			while(x&&t[x].t[c]==y) {
				t[x].t[c]=nq;
				x=t[x].fa;
			}
		}
	}
}

int main () {
	scanf("%d%d",&n,&m);
	tot=last=1;
	for(int i=1; i<=n; i++) {
		char c=getchar();
		while(c<'A'||c>'Z')
			c=getchar();
		insert(c-'A');
	}
	for(int i=1; i<=m; i++) {
		char c=getchar();
		while(c<'A'||c>'Z')
			c=getchar();
		b[i]=c-'A';
	}
	int len=1,ans=0;
	while(len<=m) {
		int now=1;
		while(len<=m&&t[now].t[b[len]])
			now=t[now].t[b[len++]];
		ans++;
	}
	printf("%d\n",ans);
	return 0;
}


猜你喜欢

转载自www.cnblogs.com/mysh/p/11809560.html
今日推荐