类型1:匹配子字符串在母串中第几个位置开始出现。
类型2:子串在母串中出现了几次(可以有重复的)。
子串:AZA
母串:AZAZAZA
sum = 3;
类型3:母串中最多有几个子串。
类型4:需要再补几个字符能构成一个类似手链那样循环相同的。
abca ->2
abcde->5
aaa->0
类型5:给出一字符串,找出由2个或2个以上相同的子字符串组成的前缀,输出前缀长度及其相同的子字符串数。
类型6:最小循环节有几个。
类型7:
匹配子字符串在母串中第几个位置开始出现
题目名称: Number Sequence
#include
#include
#include
using namespace std;
int n;
int a[1000005];
int b[10005];
int nextp[10005];
int temp1;
int temp2;
/*--------------------------------------------------------*/
void getnext()
{
int len = temp2;
int i = 0;
int j = -1;
nextp[0] =-1;
while (i<len)
{
if(j==-1||b[i]==b[j])
nextp[++i] = ++j;
else j = nextp[j];
}
}
void kmp()
{
getnext();
int i = 0;
int j = 0;
while (i<temp1&&j<temp2)
{
if(j==-1||a[i]==b[j])
{
i++;
j++;
}
else
j = nextp[j];
}
if(j==temp2)
printf("%d\n",i-j+1);
else printf("-1\n");
}
/*--------------------------------------------------------*/
int main()
{
scanf("%d",&n);
while (n--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(nextp,0,sizeof(nextp));
scanf("%d %d", &temp1, &temp2);
for (int i = 0; i < temp1; i++)
scanf("%d", &a[i]);
for (int i = 0; i < temp2; i++)
scanf("%d", &b[i]);
kmp();
}
}
子串在母串中出现了几次(可以有重复的)
题目名称:Oulipo
#include
#include
#include
using namespace std;
int n;
int count = 0;
char a[1000005];
char b[10005];
int nextt[10005];
int len1,len2;
/*-----------------------------------------*/
void getnext()
{
int i = 0;
int j = -1;
nextt[0] = -1;
while (i<len2)
{
if(j==-1||b[i]==b[j])
nextt[++i] = ++j;
else j = nextt[j];
}
}
void kmp()
{
getnext();
int i = 0;
int j = 0;
while (i<len1)
{
if(j==-1||a[i]==b[j])
{
i++;
j++;
}
else j = nextt[j];
if(j==len2)
{
count++;
j = nextt[j];
}
}
}
/*-----------------------------------------*/
int main()
{
scanf("%d",&n);
getchar();
while (n--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(nextt,0,sizeof(nextt));
count = 0;
scanf("%s",b);
scanf("%s",a);
len1 = strlen(a);
len2 = strlen(b);
//printf("%d\n%d\ndd",len1,len2)
kmp();
printf("%d\n",count);
}
}
母串中最多有几个子串。
题目名称:剪花布条
#include
#include
#include
using namespace std;
char a[1005];
char b[1005];
int nextt[1005];
int len1,len2;
int count = 0;
/*------------------------------------------------------------------*/
void getnext()
{
int i =0;
int j =-1;
nextt[0]=-1;
while (i<len2)
{
if(j==-1||b[i]==b[j])
nextt[++i] = ++j;
else j = nextt[j];
}
}
void kmp()
{
getnext();
int i = 0;
int j = 0;
while (i<len1)
{
if(j==-1||a[i]==b[j])
{
i++;
j++;
}
else j = nextt[j];
if(j==len2)
{
count++;
j = 0;
}
}
printf("%d\n",count);
}
/*------------------------------------------------------------------*/
int main()
{
while (1)
{
count = 0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(nextt,0,sizeof(nextt));
scanf("%s",a);
if(strcmp(a,"#")==0)break;
scanf("%s",b);
len1 = strlen(a);
len2 = strlen(b);
kmp();
}
}
需要再补几个字符能构成一个类似手链那样循环相同的。
题目名称: Cyclic Nacklace
#include
#include
#include
using namespace std;
int n;
char b[100005];
int len2;
int nextt[100005];
/*------------------------------------------------------------------*/
void getnext()
{
int j = -1;
nextt[0] =-1;
for(int i =0;i<len2;)
{
if(j == -1||b[i]==b[j])
nextt[++i] = ++j;
else j = nextt[j];
}
}
void result()
{
getnext();
int temp = len2 - nextt[len2];
if ((len2%temp==0)&&(temp!=len2))
printf("0\n");
else
printf("%d\n",temp-nextt[len2]%temp);
}
/*------------------------------------------------------------------*/
int main()
{
scanf("%d",&n);
while (n--)
{
//这是杭电的一道题,这里初始化会wa,具体原因不太清楚
//memset(b,0,sizeof(b));
//memset(nextt,0,sizeof(nextt));
scanf("%s",b);
len2 = strlen(b);
result();
}
}
给出一字符串,找出由2个或2个以上相同的子字符串组成的前缀,输出前缀长度及其相同的子字符串数。
题目名称: Period
#include
#include
#include
using namespace std;
int c = 1;
char b[1000005];
int nextt[1000005];
int len2;
void getnext()
{
int j =-1;
nextt[0] = -1;
for(int i = 0;i<len2;)
{
if(j==-1||b[i]==b[j])
nextt[++i] = ++j;
else j = nextt[j];
}
}
void result()
{
getnext();
for(int i = 2;i<=len2;i++)
{
if (nextt[i] != 0)
{
int temp = i -nextt[i];
if(i%temp==0&&i/temp>1)
printf("%d %d\n",i,i/temp);
}
}
printf("\n");
}
int main()
{
while (1)
{
memset(b,0,sizeof(b));
memset(nextt,0,sizeof(nextt));
scanf("%d", &len2);
if (len2 == 0)
break;
scanf("%s",b);
printf("Test case #%d\n", c);
c++;
result();
}
}
最小循环节有几个。(必须是s= a n a^n an的类型)
题目名称: Power Strings
#include
#include
#include
using namespace std;
char b[1000005];
int len2;
int nextt[1000005];
void getnext()
{
int j =-1;
nextt[0]=-1;
for(int i = 0;i<len2;)
{
if(j==-1||b[i]==b[j])
nextt[++i] = ++j;
else
{
j = nextt[j];
}
}
}
void result()
{
getnext();
int temp = len2 - nextt[len2];
if(temp==len2||len2%temp!=0)printf("1\n");
else
{
printf("%d\n",len2/temp);
}
}
int main()
{
while (1)
{
memset(b,0,sizeof(b));
scanf("%s",b);
if(strcmp(b,".")==0)
break;
len2 = strlen(b);
result();
}
}
题目名称:Seek the Name, Seek the Fame
#include
#include
#include
using namespace std;
int num[1000005];
char b[1000005];
int len2;
int nextt[1000005];
int count = 0;
void getnext()
{
int j =-1;
nextt[0]=-1;
for(int i = 0;i<len2;)
{
if(j==-1||b[i]==b[j])
nextt[++i] = ++j;
else
{
j = nextt[j];
}
}
}
void result()
{
getnext();
int t = nextt[len2];
while (t!=-1)
{
num[count++] = t;
t = nextt[t];
}
for(int i = count-2;i>=0;i--)
printf("%d ",num[i]);
printf("%d\n",len2);
}
int main()
{
while (scanf("%s",b)!=EOF)
{
memset(nextt,0,sizeof(nextt));
memset(num,0,sizeof(num));
count = 0;
len2 = strlen(b);
result();
memset(b,0,sizeof(b));
}
}