KMP之前没学,然后排位赛又有一道题考了这个知识点,这题AC了一列人,就差我一个……
KMP算法:建立一个next函数,从而使字符串匹配的时间复杂度由O(n*n)变成O(n+m)。
举个例子:
ababcab 和 abbbcabdc
首先建立next数组,next[0] = -1
ababcab
-10012012就是next数组了
很简单吧…..emmmmmmm,其实我也不太会讲,有点麻烦,不懂得去B站翻翻视频看看
例题:
字符串什么的,最喜欢了
Time Limit: 2000/1000ms (Java/Others)
Problem Description:
对于一个字符串,可以在后面添加字符,怎么添加最少的字符使得这个字符串变成由一个至少两遍前缀循环而成.
Input:
第一行输入一个T。总共T组数据 第二行输入一个字符串,( 3 <= 长度 <= 100000 ).
Output:
最少的添加的字符个数,每个输出占一行。 提示: qweqwe 刚好两遍循环,所以添加0 qweqe 没有两遍,所以添加为5,字符为qweqe 。. ababa 有两遍循环,但是第三次不完整,所以添加数为1.
Sample Input:
3 aaa abca abcde
Sample Output:
0 2 5
AC的标程代码(带解析):
// 1 题目要求的是给定一个字符串,问我们还需要添加几个字符可以构成一个由n个循环节组成的字符串。
// 2 可知我们应该先求出字符串的最小循环节的长度:假设字符串的长度为len,那么最小的循环节就是cir = len-next[len] ; 如果有len%cir == 0,那么这个字符串就是已经是完美的字符串,不用添加任何字符;如果不是完美的那么需要添加的字符数就是cir - (len-(len/cir)*cir)),相当与需要在最后一个循环节上面添加几个。
// 3 如果cir = 1,说明字符串只有一种字符例如“aaa” ; 如果cir = m说明最小的循环节长度为m,那么至少还需m个;如果m%cir == 0,说明已经不用添加了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 100010
char s[N];
int nextval[N];
int len;
void getnext(const char *s)
{
int i = 0, j = -1;
nextval[0] = -1;
while(i != len)
{
if(j == -1 || s[i] == s[j])
nextval[++i] = ++j;
else
j = nextval[j];
}
}
int main()
{
int ncase;
int length, add;
scanf("%d", &ncase);
while(ncase--)
{
scanf("%s", s);
len = strlen(s);
getnext(s);
/* for(int i = 0; i <= len; ++i) //查看next数组的内容
cout<<nextval[i]<<" ";
cout<<endl;
length = len - nextval[len]; //循环节的长度
cout << length <<endl;*/
if(len != length && len % length == 0) //循环多次
printf("0\n");
else
{
add = length - nextval[len] % length; //取余的作用:abcab,去掉abc
printf("%d\n",add);
}
}
return 0;
}
附上个博客:http://www.cnblogs.com/jackge/archive/2013/01/05/2846006.html 我就是看这个博客懂的这题