[Aizu] ALDS1_14_B: String Search[续]
Posted by-sknight
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Aizu] ALDS1_14_B: String Search[续]相关的知识,希望对你有一定的参考价值。
题目
传送门: ALDS1_14_B: String Search
描述
寻找字符串P在一个文本T中出现的位置, 输出所有在T中找到的P的索引, T的索引从0开始.
输入
第一行, 给出一个文本T, 在第二行, 给出一个字符串P
输出
每行输出一个在T中找到的P的下标, 以升序输出
限制条件
- \\(1 \\leq length of T \\leq 1000000\\)
- \\(1 \\leq length of P \\leq 10000\\)
- 输入由字母字符和数字组成
样例输入1
aabaaa
aa
样例输出1
0
3
4
样例输入2
xyzz
yz
样例输出2
1
样例输入3
abc
xyz
样例输出3
求解
分析
KMP算法讲解参见:KMP算法简明教程
以下的所有解释都是出自上述文章, 稍有修改, 以自己可以理解的形式重述了一遍.
KMP算法步骤如下
- 初始化i, j均为0
- 依次往后比较T[i], P[j], 如果相等, i与j都加一, 否则保持i不变, j=k. 如果j=k之后为-1, 那么i与j都加一
- 重复步骤2
关于k的说明:
在匹配到T[i] != P[j]时, 假设需要让 j=k, 然后继续匹配, 那么就有T[i]之前的k个字符与P[k]之前的k个字符相同, 记作 T[i - k, i -1] = P[0, k - 1], 由于是在匹配到T[i]与P[j]的时候才不相等, 那么T[i]之前的k个字符肯定与P[j]之前的k个字符相同, 记作 T[i - k, i - 1] = P[j - k, j - 1], 由此, 可以得到新的关系式 P[0, k - 1] = P[j - k, j - 1], 即在P中寻找到最大的k(0 < k < j), 使得前式成立, P中j之前的k个字符与从0开始的k个字符相同.
递推见设计部分(不是优化版本的, 因为已经很头晕了emmm)
设计
记 k = nx[j];
nx[0] = -1; 配合KMP步骤第2条使用
nx[1] = 0; 虽然前面有1个匹配到了, 但是如果写成1的话还是比较自己, 所以一般都写0
设 k = nx[j] 便有 P[0, k - 1] = P[j - k, j - 1]
如果 P[k] = P[j] 那么就有 P[0, k] = P[j - k, j]
nx[j + 1] = k + 1;
如果 P[k] != P[j], 那么令k‘ = nx[k];
如果 P[k‘] = P[j], 那么 nx[j + 1] = nx[k‘] + 1;
否则重复, 直到 k‘ = -1 此时 nx[j + 1] = 0;我写的如下:
nx[0] = -1;
nx[1] = 0;
for (i = 1; i < P_len; i++)
int k = i;
while (nx[k] != -1)
if (P[nx[k]] == P[i])
break;
k = nx[k];
nx[i + 1] = nx[k] + 1;
编码
#include <bits/stdc++.h>
using namespace std;
#define MAX_P 10005
#define MAX_T 1000005
char T[MAX_T], P[MAX_P];
int nx[MAX_P];
int main(void)
ios::sync_with_stdio(false);
cin.tie(0);
int i, j;
cin.getline(T, MAX_T);
int T_len = cin.gcount() - 1;
cin.getline(P, MAX_P);
int P_len = cin.gcount() - 1;
nx[0] = -1;
nx[1] = 0;
for (i = 1; i < P_len; i++)
int k = i;
while (nx[k] != -1)
if (P[nx[k]] == P[i])
break;
k = nx[k];
nx[i + 1] = nx[k] + 1;
i = 0;
j = 0;
while (i < T_len)
if (T[i] == P[j])
i++;
j++;
if (j == P_len)
cout << i - j << endl;
j = nx[j]; // j在++之后不会为0
else
j = nx[j];
if (j == -1)
i++;
j++;
结果
通过了, 不过时间相较别人的比较长
总结
之前都不知道这个算法叫什么, 傻傻的看别人的代码, 以为真能悟出来, 最后好久之后才知道了叫做KMP算法, 之后就可以去看思想了, 比只看代码好多了
以上是关于[Aizu] ALDS1_14_B: String Search[续]的主要内容,如果未能解决你的问题,请参考以下文章
Aizu - ALDS1_7_B Binary Trees(二叉树的表达)
c_cpp http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_3_B&lang=jp