题目描述
给出两个字符串 s_1s1 和 s_2s2,若 s_1s1 的区间 [l, r][l,r] 子串与 s_2s2 完全相同,则称 s_2s2 在 s_1s1 中出现了,其出现位置为 ll。
现在请你求出 s_2s2 在 s_1s1 中所有出现的位置。定义一个字符串 ss 的 border 为 ss 的一个非 ss 本身的子串 tt,满足 tt 既是 ss 的前缀,又是 ss 的后缀。
对于 s_2s2,你还需要求出对于其每个前缀 s's′ 的最长 border t't′ 的长度。输入格式
第一行为一个字符串,即为 s_1s1。
第二行为一个字符串,即为 s_2s2。输出格式
首先输出若干行,每行一个整数,按从小到大的顺序输出 s_2s2 在 s_1s1 中出现的位置。
最后一行输出 |s_2|∣s2∣ 个整数,第 ii 个整数表示 s_2s2 的长度为 ii 的前缀的最长 border 长度。输入输出样例
输入 #1复制
ABABABC ABA输出 #1复制
1 3 0 0 1
#include<stdio.h>
#include<string.h>
long long int next[1000005]= {0},vis[1000005];//记录最大相同前后缀的长度
char a[1000005],b[1000005];
long long int lena,lenb;
void nn(char t[],long long int next[])//记录不相等时j指针要跳回的位置
{
int i;
int j;
next[0]=-1;
i=0,j=-1;
while(i<strlen(t))
{
if(j==-1||t[i]==t[j])
{
i++;
j++;
vis[i]=j;
if(t[i]==t[j])
next[i]=next[j];
else
next[i]=j;
}
else
j=next[j];
}
}
void cmp(char a[],char b[])//!!!自定义函数无返回值要用void,用int会运行错误
{
nn(b,next);
int j=0,i=0;while(i<lena)
{
if(j==-1||a[i]==b[j])
{
j++;
i++;}
else
j=next[j];
//printf("i=%d j=%d\n",i,j);
if(j>=lenb)
{
printf("%d\n",i-lenb+1);
j=next[j];
}
}
}
int main()
{
scanf("%s",a);
scanf("%s",b);
lena=strlen(a),lenb=strlen(b);
//printf("len=%d\n",lena);
cmp(a,b);
for(int i=1; i<=lenb; i++)
printf("%d ",vis[i]);
}
总结:kmp挺抽象的,今天发现编译器上只能复制四千多个字符
奶牛们非常享受在牛栏中哞叫,因为她们可以听到她们哞声的回音。虽然有时候并不能完全听到完整的回音。Bessie曾经是一个出色的秘书,所以她精确地纪录了所有的哞叫声及其回声。她很好奇到底两个声音的重复部份有多长。
输入两个字符串(长度为1到80个字母),表示两个哞叫声。你要确定最长的重复部份的长度。两个字符串的重复部份指的是同时是一个字符串的前缀和另一个字符串的后缀的字符串。
我们通过一个例子来理解题目。考虑下面的两个哞声:
moyooyoxyzooo
yzoooqyasdfljkamo
第一个串的最后的部份"yzooo"跟第二个串的第一部份重复。第二个串的最后的部份"mo"跟第一个串的第一部份重复。所以"yzooo"跟"mo"都是这2个串的重复部份。其中,"yzooo"比较长,所以最长的重复部份的长度就是5。
输入格式
* Lines 1..2: Each line has the text of a moo or its echo
输出格式
* Line 1: A single line with a single integer that is the length of the longest overlap between the front of one string and end of the other.
输入输出样例
输入 #1复制
abcxxxxabcxabcd abcdxabcxxxxabcx输出 #1复制
11说明/提示
#include<stdio.h>
#include<string.h>long long int next[1000005]= {0};
char a[1000005],b[1000005];
long long int lena,lenb;void nn(char t[],long long int next[])
{
int i;
int j;
next[0]=-1;
i=0,j=-1;
while(i<strlen(t))
{
if(j==-1||t[i]==t[j])
{
i++;
j++;next[i]=j;
}
else
j=next[j];
}
}
int cmp(char a[],char b[],int lena)
{
nn(b,next);
int j=0,i=0;while(i<lena)
{
if(j==-1||a[i]==b[j])
{
j++;
i++;}
else
j=next[j];
//printf("i=%d j=%d\n",i,j);
}
return j;}
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int main()
{
scanf("%s",a);
scanf("%s",b);
lena=strlen(a),lenb=strlen(b);
//printf("len=%d\n",lena);printf("%d",max(cmp(a,b,lena),cmp(b,a,lenb)));
}
思路:利用kmp,将第二串和第一串进行比对,直到比对到第一串的最后一个字符,如果相等,就说明最大长度就是第二串比对到的位置,如果不是,就回溯
明日计划:学一下二维数组在函数中的调用,了解一下map的用法