牛客小白月赛28 G 牛牛和字符串的日常(KMP)

 G 牛牛和字符串的日常

题目描述 

牛牛每天都要做的事就是读书,从书里找自己喜欢的句子,他每天都会去读一本书,如果牛牛今天读的书的某连续{}kk个字符刚好是牛牛喜欢句子的某个前缀,那么牛牛将得到{}kk点兴奋感,但他每天只能注意到一次自己喜欢的句子(也就是每天只能增加一次兴奋感),也就是说他会尽量去找那个让自己兴奋度增加最多的句子,那么,{}nn天之后牛牛总共最多能有多少兴奋感?

输入描述:

第一行是一个字符串s(∣s∣<=1×105)表示牛牛喜欢的字符串第二行是一个整数n,表示总共经历了n天(n<=100){}第二行是一个整数n,表示总共经历了n天(n<=100)接下来n行每行一个字符串t_i(|t_i|<=1×10^5),分别表示牛牛第i天读的书接下来n行每行一个字符串ti​(∣ti​∣<=1×105),分别表示牛牛第i天读的书

 输出描述:

输出这n天来牛牛最大能获得的兴奋感

 数据:略

思路: 

 kmp中next数组代表着前缀和后缀相同的最大长度,当匹配过程中,可以把模式串当成后缀,记录每个位置的next,取最大值即可;

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+7;
char p[N],s[N];//p是模式串(短),s是文本串(长) 
int ne[N];//next[j]就是待匹配串从t[0]开始到t[j-1]结尾的这个子串中,前缀和后缀相等时对应前缀/后缀的最大长度
int main()
{
	cin >>s+1;
	int t;cin >>t;	
	int ans=0; 
	int n=strlen(s+1);
	for(int i=2,j=0;i<=n;i++)//先求模式串本身的next数组 
	{
		while(j&&s[i]!=s[j+1]) j=ne[j];
		if(s[i]==s[j+1]) j++;
		ne[i]=j;
	}
	//for(int i=1;i<=n;i++) cout <<ne[i];
	while(t--)
	{
		cin >>p+1;
		int m=strlen(p+1); 
		int cnt=0;
		for(int i=1,j=0;i<=m;i++)
		{
			while(j&&p[i]!=s[j+1]) j=ne[j];
			if(p[i]==s[j+1]) j++; 
			cnt=max(cnt,j);
			if(j==n) j=ne[j]; 
		}
		ans+=cnt;
	}
	cout <<ans<<endl;
}

 

©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页