题目:pku3167,pku1226,pku3450,pku3461,pku3080,pku2185,pku2752,pku2406,pku1961,pku2541
pku2406:
题意:For each s you should print the largest n such that s = a^n for some string a.。即求一个字符串的最大重复字串。用kmp中next[]函数来求解。
① len==1||s[next[len-1]]!=s[len-1] ans=1;
② len%(len-next[len])==0 ans= len/(len-next[len]);
pku1961
题意:类似pku2406,这里也是求重复字串,只是稍微改一下就可以了。
i=2;i<=len; ans=i/(i-next[i])(if i%(i-next[i])==0)
pku2752
题意:首尾对称的
for(i=len-1;i>=0;i=next[i])
{
ans[++k]=i+1;
if(s[i]!=s[next[i]])break;
}
pku3461 KMP
题意:求子串在文本串中出现了多少次,这里只需要在kmp模板里稍微改一下就ok了!
int kmp(char*T,char*s)
{
int i,j,count;
i=0;
j=0;
count=0;
while(i<len2&&j<len1)
{
if(j==-1||T[i]==s[j])
{
i++;
j++;
}
else
j=next[j];
if(j==len1)
{
count++;
j=next[j];
}
}
return count;
}
pku2185(KMP求一个矩形字符串的最小重复串)
题意:求一个由字符构成的矩形的最小重复子矩阵
ABABAB //最小重复AB 当前len=2
ABCABC //最小重复ABC 当前len=3
所以此时 对于这两行的最小重复为6 当前len=lcu(2,3)=6;
所以做此题目的关键在于每一行的最小重复串 这里可以用kmp中的next[]很好的解决此问题,然后求其最小公倍数
找出n行的最小重复串(ans1)即可(当然最小重复串肯定不能大于m) ,得出
类似的求出列的最小的重复串(ans2)结果就是ans1*ans2
pku3080 kmp+枚举字串
int main()
{
int i,j,k,l,len,t;
scanf("%d",&t);
while(t--)
{
len=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%s",s[i]);
//枚举第一行的串,接着枚举每个匹配字串的长度,然后与后n-1行的串匹配
for(i=1;i<=60;i++)//枚举字串的长度
{
for(j=0;j<=60-i;j++)//从j开始到j+i的字符串
{
for(k=j,l=0;k<j+i;k++,l++)
str[l]=s[1][k];//长度为i的字串
str[l]='/0';//因为没有加这一句话,WA暴了,快疯了
if(check(str,n))//枚举的子串与2-->n行的串都匹配成功
{
if(len<i)
{
len=i;
strcpy(ans,str);
}
else if(len==i)//同等长度的字串,找字典顺序小的
{
if(strcmp(ans,str)>0)//判断……
strcpy(ans,str);
}
}
}
}
if(len>=3)
printf("%s/n",ans);
else
printf("no significant commonalities/n");
}
return 0;
}
pku3450 1226KMP +枚举
题意:这题和pku3080应该就是一样的,只是len不一样而已
pku3167 kmp好题
题意:这里匹配的不是一个字符或数字。这里匹配的当前数字在该串中的大小
T[] 2 10 10 7 3 2
S[] 1 4 4 3 2 1
这里的两个串是可以匹配成功的 我们可以将每一个数转换成在该串的大小
T[] 1 4 4 3 2 1 //2是第一小的 ,10是第4小的,……
S[] 这个串也类似的变换
T[i]与S[j]匹配
这里我们要算出T[i]在已经匹配的串中比T[i]小的数的个数,和与T[i]相等的数的个数(如果这两个都相等,当然比之大的也相等)
#include<stdio.h>
#include<string.h>
#include"algorithm"
using namespace std;
int a[100100],b[25100],next[25100];
int ans[100100];
int p[25100][26],q[100100][26];
void getnext(int len)
{
int i,j,k,equali,equalj,smalli,smallj;
i=0;
j=-1;
next[0]=-1;
while(i<len)
{
smalli=smallj=0;
for(k=1;k<b[j];k++)
smallj+=p[j][k];
equali=p[j][b[j]];
for(k=1;k<b[i];k++)
smalli+=(p[i][k]-p[i-j-1][k]);
equalj=p[i][b[i]]-p[i-j-1][b[i]];
if(j==-1||(equali==equalj&&smalli==smallj))
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp(int len1,int len2)
{
int i,j,equali,equalj,smalli,smallj,k,count;
count=0;
i=0;
j=0;
while(i<len1&&j<len2)
{
smalli=0;
smallj=0;
for(k=1;k<b[j];k++)
smallj+=p[j][k];
equalj=p[j][b[j]];
if(i>j)
{
for(k=1;k<a[i];k++)
smalli+=q[i][k]-q[i-j-1][k];
equali=q[i][a[i]]-q[i-j-1][a[i]];
}
else
{
for(k=1;k<a[i];k++)
smalli+=q[i][k];
equali=q[i][a[i]];
}
if(j==-1||(smalli==smallj&&equali==equalj))
{
i++;
j++;
}
else
j=next[j];
if(j==len2)
{
count++;
ans[count]=i-len2;
j=next[j];
}
}
return count;
}
int main()
{
int n,k,s,i,j,num;
while(scanf("%d%d%d",&n,&k,&s)!=EOF)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<k;i++)
scanf("%d",&b[i]);
q[0][a[0]]=p[0][b[0]]=1;
for(i=1;i<n;i++)
{
for(j=1;j<=s;j++)
q[i][j]=q[i-1][j];
q[i][a[i]]++;
}
for(i=1;i<k;i++)
{
for(j=1;j<=s;j++)
p[i][j]=p[i-1][j];
p[i][b[i]]++;
}
getnext(k);
num=kmp(n,k);
printf("%d/n",num);
for(i=1;i<=num;i++)
printf("%d/n",ans[i]+1);
}
return 0;
}