您的位置:首页 > 大数据 > 人工智能

HDU - 4300 - Clairewd’s message (扩展KMP)

2017-09-09 22:32 441 查看
HDU - 4300 - Clairewd’s message

将 S 看成密文,转化成明文 T ,那么答案应该是S 的后缀与 T 的前缀的最小公共部分。

可以转化为求 S[i...n] 与 T 的最长公共前缀。这样可以用扩展KMP来做。

扩展KMP

扩展KMP解决求 S1[i..n] 与 S2 的最长公共前缀,ext[i] 就是其值。

next[i] 的值为 S2[i...n] 与 S2 的最长公共前置。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
char S
,T
;
int nxt
,ex
,n;
//① P=nxt[po]+po,即最长能匹配到的地方。
//此时s[0,P-po]=S[po,P]
//那么s[i-po,P-po]=s[i,P]
//注意nxt的定义,可以得到如下结论。
//如果nxt[i-po]+i<P ,即不能延伸P的位置,那么此时nxt是确定的。

//② 如果延伸超过了,那么要重新计算P和po,
//因为s[i-po]=s[i,P],所以只需要从原来的P开始就行了。

//getNext是自己在自己身上求extend
//所以求extend的过程与求Next差不多。
void getNext(char s[])
{
int i=0,j,po;
nxt[0]=n;
while(i+1<n&&s[i]==s[i+1]) ++i;
nxt[1]=i;
po=1;
for(i=2;i<n;++i)
{
if(nxt[i-po]+i<nxt[po]+po)
nxt[i]=nxt[i-po];
else
{
j=max(0,nxt[po]+po-i);
while(i+j<n&&s[j]==s[j+i]) ++j;
nxt[i]=j;
po=i;
}
}
}

//求出s1[i,...,n-1]与s2的最长公共前缀
void exkmp(char s1[],char s2[])
{
int i=0,j,k,po;
while(s1[i]==s2[i]&&i<n) ++i;
ex[0]=i;
po=0;
for(i=1;i<n;++i)
{
if(nxt[i-po]+i<ex[po]+po)
ex[i]=nxt[i-po];
else
{
j=max(0,ex[po]+po-i);
while(i+j<n&&j<n&&s1[j+i]==s2[j]) ++j;
ex[i]=j;
po=i;
}
}
}
char f[30],inv[30];
int main()
{
int kase;
scanf("%d",&kase);
while(kase--)
{
scanf("%s",f);
scanf("%s",S);
for(int i=0;i<26;++i)
inv[f[i]-'a']=i+'a';
n=strlen(S);
for(int i=0;i<n;++i) T[i]=inv[S[i]-'a'];
T
=0;
getNext(T);
exkmp(S,T);
int L=(n+1)/2;
for(int i=(n+1)/2;i<n;++i,++L)
if(ex[i]+i==n) break;
for(int j=0;j<L;++j) putchar(S[j]);
for(int j=0;j<L;++j) putchar(inv[S[j]-'a']);
puts("");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: