HDU 4622 Reincarnation
来源:互联网 发布:程序员有含金量的证书 编辑:程序博客网 时间:2024/06/07 13:45
ProblemDescription
Now you are back,andhave a task to do:
Given you a string s consist of lower-case English letters only,denote f(s) asthe number of distinct sub-string of s.
And you have some query,each time you should calculate f(s[l...r]), s[l...r]means the sub-string of s start from l end at r.
Input
The first linecontains integer T(1<=T<=5), denote the number of the test cases.
For each test cases,the first line contains a string s(1 <= length of s<= 2000).
Denote the length of s by n.
The second line contains an integer Q(1 <= Q <= 10000),denote the numberof queries.
Then Q lines follows,each lines contains two integer l, r(1 <= l <= r<= n), denote a query.
Output
For each testcases,for each query,print the answer in one line.
Sample Input
2
bbaba
5
3 4
2 2
2 5
2 4
1 4
baaba
5
3 3
3 4
1 4
3 5
5 5
Sample Output
3
1
7
5
8
1
3
8
5
1
题目大意:给一个字符串,进行q次询问,求l到r之间的字符串有多少个不同子串。
方法:开始用后缀数组暴力做的,结果果断T掉了。后来看了看CLJ的后缀自动机,然后在网上有查了些后缀自动机的资料(感觉这篇写得不错。http://blog.csdn.net/xuezhongfenfei/article/details/12262941)就试着用后缀自动机写了。对于后缀自动机。我们先将l和r按照l从小到大,排序。对于l相同,r从小到大排序。这样对于l相同的询问,就可以利用后缀自动机的特性往后面加字符得到答案。对于l不同的询问,就重新建立自动机。
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<deque>#include<algorithm>using namespace std;struct NODE{int left ,right;int num;};struct State{State *pre ,*go[26];//pre是上一个可以接收后缀的结点int val;};State * root ,* tail ,que[4010];NODE nodes[10010];int ans[10010];int n ,q ,tot ,sum ,len;char str[2010];int cmp(NODE a ,NODE b){if(a.left==b.left){return a.right < b.right;}return a.left < b.left;}void init(){memset(que,0,sizeof(que));tot = 0;len = 0;root = tail = &que[tot++];}void add(int w ){State *p = tail ,*np = &que[tot++];np->val = len;//找到上一个能接受后缀的节点while(p && p->go[w]==NULL){p->go[w] = np;p = p->pre;}//如果没有找到这样的节点,就将pre指针指向rootif(p==NULL){np->pre = root;}//如果找到这样的节点,就把这个节点pre就指向这个节点对应的儿子else{State *q = p->go[w];if(p->val + 1==q->val){np->pre = q;}else{State *nq = &que[tot++];//将q的指针赋值给nq,将nq的pre指向p,将np和q的pre指向nq*nq = *q;nq->val = p->val + 1;q->pre = np->pre = nq;//同时将p的儿子为w且指向q的全部指向nqwhile(p && p->go[w]==q){p->go[w] = nq;p = p->pre;}}}tail = np;}int solve(){ sum = 0; for(int i = tot - 1;i > 0;i--) { sum += que[i].val - que[i].pre->val; }return sum;}int main(){int x;scanf("%d",&n);while(n--){scanf("%s",str+1);scanf("%d",&q);for(int i = 1;i<=q;i++) {scanf("%d%d",&nodes[i].left,&nodes[i].right);nodes[i].num = i; }sort(nodes + 1,nodes + q + 1,cmp);nodes[0].left = -1;for(int i = 1;i<=q;i++){if(nodes[i].left!=nodes[i-1].left){init();for(int j = nodes[i].left;j <= nodes[i].right;j++){len++;add(str[j] - 'a');}ans[nodes[i].num] = solve();x = nodes[i].right + 1;}else{if(nodes[i].right==nodes[i-1].right){ans[nodes[i].num] = ans[nodes[i-1].num];}else{for(int j = x;j <= nodes[i].right;j++){len++;add(str[j] - 'a');}ans[nodes[i].num] = solve();x = nodes[i].right + 1;}}}for(int i = 1;i <= q;i++){printf("%d\n",ans[i]);}}return 0;}
- HDU 4622 Reincarnation
- HDU-4622-Reincarnation
- hdu 4622Reincarnation
- HDU 4622 Reincarnation SAM
- HDU 4622 Reincarnation
- HDU 4622 Reincarnation
- HDU 4622 Reincarnation
- hdu 4622 Reincarnation
- hdu 4622 Reincarnation
- hdu 4622 Reincarnation (后缀自动机)
- hdu 4622 Reincarnation (后缀自动机)
- hdu 4622 Reincarnation(SAM)
- HDU 4622 Reincarnation 后缀自动机
- hdu 4622 Reincarnation(hash)
- hdu 4622 Reincarnation(后缀数组)
- [后缀数组+枚举] hdu 4622 Reincarnation
- hdu 4622 Reincarnation(后缀数组)
- hdu 4622 Reincarnation(后缀树组求子串个数)
- C/C++内存分配知识
- 测试
- 做出上述表述的高管是谷歌首席财务官
- Linux异步通知 fasync
- 明天开始专心找工作
- HDU 4622 Reincarnation
- 【题解】[scoi2009]迷路
- Java学习第13天:String和StringBuffer
- LZCreat技术开发团队
- Android:Layout_weight的深刻理解
- POJ 1396 Simple Arithmetics
- 凹三角形和凸三角形
- 看探索股票投资之谜有感
- oracle sql