KMP匹配问题、求字符串的周期、Cyclic Nacklace
来源:互联网 发布:html5 javascript 联系 编辑:程序博客网 时间:2024/06/06 20:57
本文中一共有3个问题,一共有3个求next的方法。
问题一,KMP匹配问题,用的是精确(高效)的求next的方法(来自紫红色的清华大学数据结构课本)
问题二,求字符串的周期,用的是自己写的求next的方法
问题三,求构成有周期的字符串至少需要补多少字符,用的是普通的求next的方法(也来自上述课本)
三个问题都已经AC了,下面贴出来的代码也都是AC了的。
然而,问题二的代码中的next,只能用来求周期,如果用来KMP匹配果断错
看来我对KMP仍然很不熟悉,如果本文有错误,欢迎指正!
精确的和普通的,效率是不一样的,一个是θ(m+n),一个是O(m*n)
也就是说,普通的next在匹配aaaaaaaaaaaaaaaaaaaa和aaaab的时候效率是很低的,
精确的next处理掉了这个问题,但同时也失去了短串本身的周期性质。
KMP匹配问题
题目:
Description
Input
Output
Sample Input
213 51 2 1 2 3 1 2 3 1 3 2 1 21 2 3 1 313 51 2 1 2 3 1 2 3 1 3 2 1 21 2 3 2 1
Sample Output
6-1
我本来是自己写的求next的方法,可惜最后超时了,我测试了一下,这个在最坏情况下确实是暴力的
我们课本上面写了2个求next数组的方法,第一个和我自己写的是一样的,第2个就是专门解决listm为1 1 1 1 1 1 2这种情况的。
于是我直接把第2个改进后的方法抄下来。。。
代码:
#include<iostream>#include<string.h>using namespace std;int listn[1000001];//长串int listm[10001];//短串int next_[10001];void getnext(int *t,int m, int *next)//m是短串t的长度{int i = 1, j = 0;next[1] = 0;while (i < m){if (j == 0 || t[i] == t[j]){i++;j++;if (t[i] != t[j])next[i] = j;else next[i] = next[j];}else j = next[j];}}int main(){ios_base::sync_with_stdio(false);//减小输入输出的时间int t, n, m;cin >> t;while (t--){cin >> n >> m;for (int i = 1; i <= n; i++)cin >> listn[i];for (int i = 1; i <= m; i++)cin >> listm[i];listm[0] = 2000000;next_[0] = 0;next_[1] = 0;int i,j;getnext(listm, m, next_);i = 1;j = 1;while (i <= n){if (listn[i] == listm[j]){i++;j++;if (j > m)break;}else{if (next_[j])j = next_[j];else{i++;j = 1;}}}if (j > m)cout << i - m;else cout << -1;cout << endl;}return 0;}
求字符串的周期
题目:
Description
Input
Output
Sample Input
abcdaaaaababab.
Sample Output
143
这个题目的next数组就是我自己写代码求的,在求上一个问题时候写的,只不过没用上。
不过本题不能用上题那种精确的求next的方法,a b c a b c a b c a b c的next是011 011 011 011
好像也可以用来求周期,但是肯定没有下面的方法这么简单。
下面的方法,根据dif差不多就直接求出来了。
dif = l - next_[l]
代码:
#include<iostream>#include<string.h>using namespace std;char c[1000001];int next_[1000001];int l;int main(){while (1){gets(c+1);l = strlen(c+1);if (l == 1 && c[1] == '.')break;next_[0] = 0;next_[1] = 0;int i, j;for (i = 2; i <= l; i++){j = i - 1;while (j && c[j] != c[next_[j]])j = next_[j];next_[i] = next_[j] + 1;}int dif = l - next_[l];if (next_[l] == 1){if (l > 1)cout << 1;else cout << l;}else if (l%dif){cout << 1;}else{if (c[l] == c[next_[l]])cout << l/dif;else cout << 1;}cout << endl;}return 0;}
这个代码是AC了的,对于求周期确实是有效的。
但是!求出来的数组next居然是错的!
我在AC之前只关注如何用next求周期,AC之后仔细一想,有问题!
比如输入aaabbbaaa,求的next居然是012333343。。。
也就是说,我写错了,这个数组确实记录了字符串的周期信息,然而却没法拿去匹配。
虽然不影响本题的AC,但是知道这个结果还是感觉自己好low啊
Cyclic Nacklace(求构成有周期的字符串至少需要补多少字符)
题目:
Description
As Christmas is around the corner, Boys are busy in choosing christmas presents to send to their girlfriends. It is believed that chain bracelet is a good choice. However, Things are not always so simple, as is known to everyone, girl's fond of the colorful decoration to make bracelet appears vivid and lively, meanwhile they want to display their mature side as college students. after CC understands the girls demands, he intends to sell the chain bracelet called CharmBracelet. The CharmBracelet is made up with colorful pearls to show girls' lively, and the most important thing is that it must be connected by a cyclic chain which means the color of pearls are cyclic connected from the left to right. And the cyclic count must be more than one. If you connect the leftmost pearl and the rightmost pearl of such chain, you can make a CharmBracelet. Just like the pictrue below, this CharmBracelet's cycle is 9 and its cyclic count is 2:
Now CC has brought in some ordinary bracelet chains, he wants to buy minimum number of pearls to make CharmBracelets so that he can save more money. but when remaking the bracelet, he can only add color pearls to the left end and right end of the chain, that is to say, adding to the middle is forbidden.
CC is satisfied with his ideas and ask you for help.
Input
Each test case contains only one line describe the original ordinary chain to be remade. Each character in the string stands for one pearl and there are 26 kinds of pearls being described by 'a' ~'z' characters. The length of the string Len: ( 3 <= Len <= 100000 ).
Output
Sample Input
3aaaabcaabcde
Sample Output
025
代码:
#include<iostream>#include<string.h>using namespace std;char c[100005];int next_[100005];int l;void get_next(char *t, int m, int next[]){int i = 1, j = 0;next[1] = 0;while (i < m){if (j == 0 || t[i] == t[j])next[++i] = ++j;else j = next[j];}}int main(){int t;cin >> t;gets(c + 1);while (t--){gets(c + 1);l = strlen(c + 1);next_[0] = 0;next_[1] = 0;int i, j;get_next(c, l, next_);int dif = l - next_[l];if (c[l] == c[next_[l]])cout << (dif - l%dif) % dif;else cout << l;cout << endl;}return 0;}
当然了,这是我把代码重写之后的样子,第一次AC的时候自然不是这个样子(我也写不出这么变态的表达式啊)
- KMP匹配问题、求字符串的周期、Cyclic Nacklace
- HDU 3746 Cyclic Nacklace kmp处理字符串周期问题
- [HDU 3746]Cyclic Nacklace[kmp求周期]
- HDU 3746(Cyclic Nacklace)字符串匹配-KMP
- HDU 3746 Cyclic Nacklace (kmp求周期)
- HDU 3746 Cyclic Nacklace 数据结构+kmp周期类问题
- HDU 3746 Cyclic Nacklace kmp求字符串的循环节长度
- 字符串周期--hdu 3746 Cyclic Nacklace
- Cyclic Nacklace +KMP求循环节
- Cyclic Nacklace(KMP求循环节)
- HDU 3746 Cyclic Nacklace kmp处理字符串
- hdu3746 Cyclic Nacklace 利用kmp算最小周期
- hdu3746 Cyclic Nacklace(kmp周期 最小循环节)
- hdu3746—Cyclic Nacklace(kmp周期性质)
- HDU 3746 Cyclic Nacklace KMP求字符串最小循环节长度
- 【KMP】 hdu3746 Cyclic Nacklace
- HDU3746-Cyclic Nacklace(KMP)
- HDU3746 Cyclic Nacklace 【KMP】
- STL之五:set/multiset用法详解
- 树上分治
- busybox中ps命令源代码分析
- sql server的数据类型总结
- Java Spring MVC 文件下载
- KMP匹配问题、求字符串的周期、Cyclic Nacklace
- android代码混淆
- 动态规划转移方程(二)
- 链式前向星
- Scale up and Scale out
- Maven依赖Scope标签用法
- lamp安装
- 2016多校联合训练赛 第六场1003 A Simple Nim hdu 5795
- System.gc()和System.runFinalization()