列表

详情


NC24761. [USACO 2010 Dec G]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.

输入描述

* 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 

输出:

2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 15ms, 内存消耗: 9308K, 提交时间: 2019-11-02 14:48:57

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e6+150;
const int kind=26;

int tot=1,las=1;
int ch[maxn*2][kind];
int len[maxn*2],fa[maxn*2],cnt[maxn*2];
inline int read() {
    char c = getchar();
    while (!isalpha(c)) c = getchar();
    return c - 'A';
}

inline int newn(int x){len[++tot]=x;return tot;}
//简化版SAM
void sam_ins(int c){
	int p=las,np=newn(len[las]+1);las=tot;cnt[np]++;
	while(p&&!ch[p][c])ch[p][c]=np,p=fa[p];
	if(!p)fa[np]=1;
	else{
		int q=ch[p][c];
		if(len[q]==len[p]+1) fa[np]=q;
		else{
			int nq=newn(len[p]+1);
			for(int i=0;i<kind;i++)ch[nq][i]=ch[q][i];
			fa[nq]=fa[q];
			fa[q]=fa[np]=nq;
			while(p&&ch[p][c]==q) ch[p][c]=nq,p=fa[p];
		}
	}
}
int now=1;
int ans=1;
inline void solve(int v){
	if(ch[now][v]){
		now=ch[now][v];
	}
	else{
		++ans;
		now=ch[1][v];
	}
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		sam_ins(read());
	}	
	for(int i=0;i<m;i++){
		solve(read());
	}
	printf("%d\n",ans);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 19ms, 内存消耗: 9108K, 提交时间: 2020-03-02 16:24:00

#include<bits/stdc++.h>
using namespace std;


const int N=1e5+100;


int t[N][26],fa[N],len[N],lst=1,cnt=1;
int ans=1;

void insert(int c)
{
	int p=lst;
	int now=++cnt;
	len[now]=len[lst]+1;
	lst=now;
	for(;p&&t[p][c]==0;p=fa[p]) t[p][c]=now;
	
	if(p==0) fa[now]=1;
	else 
	{
		int q=t[p][c];
		if(len[q]==len[p]+1) fa[now]=q;
		else 
		{
			int nq=++cnt;
			memcpy(t[nq],t[q],sizeof t[0]);
			fa[nq]=fa[q];
			fa[q]=fa[now]=nq;
			for(;p&&t[p][c]==q;p=fa[p]) t[p][c]=nq;
		}
	} 
}
int NOW=1;
void get(int x)
{
	if(t[NOW][x]) NOW=t[NOW][x];
	else 
	{
		ans++;
		NOW=t[1][x];
	}
}
int main()
{
	int n,m;
	cin>>n>>m;
	getchar();
	
	char s;
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		insert(s-'A');
	}
	for(int i=1;i<=m;i++)
	{
		cin>>s;
		get(s-'A');
	}
	cout<<ans<<endl;
	return 0;
}

上一题