HDU 4300 Clairewd’s message(扩展kmp)

http://acm.hdu.edu.cn/showproblem.php?pid=4300

题意:
给出两个字符串,第一个字符串是加密表,是用来将明文转化成密文的。

第二个字符串是密文+明文,而且密文是完整的,但是明文不一定完整,现在要根据密文和加密表把所有明文表示出来,要求整个字符串长度最小。

思路:

看懂题意之后就比较好做了,原串的明文是后缀,现将原串根据加密表全部转化成明文,那么此时前缀就是明文,如果药整个字符串长度最小,那么确定的明文当然是越多越好了,计算一下最长公共前缀。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<map>
 5 using namespace std;
 6 const int maxn = 1000000+5;
 7 
 8 char s1[maxn],s2[maxn], p[30];
 9 int nxt[maxn],extend[maxn];
10 
11 map<char,char> mp;
12 
13 
14 void preekmp(char x[], int m)
15 {
16     nxt[0] = m;
17     int j = 0;
18     while(j+1 <m && x[j] == x[j+1])  j++;
19     nxt[1] = j;
20     int k = 1;
21     for(int i=2;i<m;i++)
22     {
23         int p = nxt[k]+k-1;
24         int L = nxt[i-k];
25         if(i+L<p+1)  nxt[i] = L;
26         else
27         {
28             j = max(0,p-i+1);
29             while(i+j<m && x[i+j]==x[j])  j++;
30             nxt[i] = j;
31             k = i;
32         }
33     }
34     return;
35 }
36 
37 void ekmp(char x[],int m,char y[],int n)
38 {
39     preekmp(x,m);
40     int j = 0;
41     while(j<n && j<m && x[j] == y[j]) j++;
42     extend[0] = j;
43     int k = 0;
44     for(int i=1;i<n;i++)
45     {
46         int p = extend[k]+k-1;
47         int L = nxt[i-k];
48         if(i+L<p+1)  extend[i]=L;
49         else
50         {
51             j = max(0,p-i+1);
52             while(i+j<n && j<m && y[i+j]==x[j])  j++;
53             extend[i] = j;
54             k = i;
55         }
56     }
57     return;
58 }
59 
60 int main()
61 {
62     //freopen("in.txt","r",stdin);
63     int T;
64     scanf("%d",&T);
65     while(T--)
66     {
67         mp.clear();
68         scanf("%s%s",p,s1);
69         int n = strlen(s1);
70         for(int i=0;p[i];i++)  mp[p[i]]='a'+i;
71         memset(s2,0,sizeof(s2));
72         for(int i=0;i<n;i++)  s2[i] = mp[s1[i]];
73         ekmp(s2,n,s1,n);
74         int ans = n;
75         for(int i=0;i<n;i++)
76         {
77             if(i+extend[i]>=n && i>=extend[i])
78             {
79                 ans = i;
80                 break;
81             }
82         }
83         for(int i=0;i<ans;i++)  printf("%c",s1[i]);
84         for(int i=0;i<ans;i++)  printf("%c",mp[s1[i]]);
85         printf("
");
86     }
87     return 0;
88 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7853507.html