题目链接:

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

Reincarnation

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)

Total Submission(s): 2096    Accepted Submission(s): 715

Problem Description
Now you are back,and have a task to do:

Given you a string s consist of lower-case English letters only,denote f(s) as the 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 line contains 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 number of queries.

Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n), denote a query.
 
Output
For each test cases,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
Hint
I won't do anything against hash because I am nice.Of course this problem has a solution that don't rely on hash.
 
Source
 
Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:  5061 5060 5059 5058 5057 

题目意思:

给一个字符串,对每一个字符串,有非常多询问,询问给定区间不同子串的个数。

解题思路:

kmp+dp

普通的dp转移肯定超时。

sa[i][j]:表示以第j个字符開始可以往前最多的字符个数(如果为s个),要求满足【j-s+1,j】在【i,j-1】字符串区间出现。

这样要统计j開始的往前的情况,能够把字符串倒过来,把j作为第一个,然后1作为最后一个,求一遍next.然后更新sa[i][j] (i<j)

求出sa[i][j]后,就能够直接转移dp[i][j]=dp[i][j-1]+i-j+1-sa[i][j] //把第j个字符加上后,对整个子串个数的影响。减去在前面已经出现的。

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std; #define Maxn 2200 char sa1[Maxn];
char sa2[Maxn];
int next[Maxn];
int n,nn;
int sa[Maxn][Maxn],dp[Maxn][Maxn]; void getnext()
{
int j=0;
next[1]=0; for(int i=2;i<=nn;i++)
{
while(j>0&&sa1[j+1]-sa1[i])
j=next[j];
if(sa1[j+1]==sa1[i])
j++;
next[i]=j;
}
return ;
}
int main()
{
int t; scanf("%d",&t);
while(t--)
{
scanf("%s",sa1+1);
n=strlen(sa1+1);
for(int i=1;i<=n;i++)
sa2[i]=sa1[n+1-i]; for(int i=1;i<=n;i++)
{ for(int j=i;j<=n;j++)
sa1[j-i+1]=sa2[j];
nn=n-i+1;
getnext();
sa[n+1-i-1][n+1-i]=next[2]; for(int j=i+2;j<=n;j++)
sa[n+1-i-(j-i)][n+1-i]=max(next[j-i+1],sa[n+1-i-(j-i)+1][n+1-i]);
} for(int i=1;i<=n;i++)
{
dp[i][i]=1;
for(int j=i+1;j<=n;j++)
dp[i][j]=dp[i][j-1]+(j-i+1)-sa[i][j]; }
int q; scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",dp[a][b]);
}
}
return 0;
}

[kmp+dp] hdu 4628 Pieces的更多相关文章

  1. HDU 4628 Pieces(DP + 状态压缩)

    Pieces 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4628 题目大意:给定一个字符串s,如果子序列中有回文,可以一步删除掉它,求把整个序列删除 ...

  2. hdu 4628 Pieces 状态压缩dp

    Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total S ...

  3. hdu 4628 Pieces 状压dp

    题目链接 枚举所有状态, 1表示这个字符还在原来的串中, 0表示已经取出来了. 代码中j = (j+1)|i的用处是枚举所有包含i状态的状态. #include <iostream> #i ...

  4. HDU 4628 Pieces(状压DP)题解

    题意:n个字母,每次可以删掉一组非连续回文,问你最少删几次 思路:把所有回文找出来,然后状压DP 代码: #include<set> #include<map> #includ ...

  5. hdu 4628 Pieces

    http://acm.hdu.edu.cn/showproblem.php?pid=4628 状态压缩DP 时间复杂度应该是 16*(2^32) 但是运行时要远小于这个数 所以加一定剪枝就可以过 代码 ...

  6. HDU 4628 Pieces(状态压缩+记忆化搜索)

    http://acm.hdu.edu.cn/showproblem.php?pid=4628 题意:给个字符窜,每步都可以删除一个字符窜,问最少用多少步可以删除一个字符窜分析:状态压缩+记忆化搜索  ...

  7. hdu 4628 Pieces(状态压缩+记忆化搜索)

    Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total S ...

  8. HDU 6153 A Secret ( KMP&&DP || 拓展KMP )

    题意 : 给出两个字符串,现在需要求一个和sum,考虑第二个字符串的所有后缀,每个后缀对于这个sum的贡献是这个后缀在第一个字符串出现的次数*后缀的长度,最后输出的答案应当是 sum % 1e9+7 ...

  9. [HDOJ5763]Another Meaning(KMP, DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5763 题意:给定两个字符串a和b,其中a中的字符串如果含有子串b,那么那部分可以被替换成*.问有多少种 ...

随机推荐

  1. 他们主动布局(autolayout)环境的图像编辑器

    hi,all: 在经过了一番犹豫之后.我决定将我自己做的这个小APP的源代码发布给大家: 其出发点是和大家一起学习iOS开发.仅供学习參考之用. 之前代码是托管与gitlab 上的,今天我将其pull ...

  2. 【Android基础】短信的发送

    //Button的点击事件 @Override public void onClick(View v) { // 接受者电话号码 Uri uri = Uri.parse("smsto:123 ...

  3. 【OC加强】辛格尔顿和[NSFileManager defaultMagager]以及其他设计模式

    我们在工作中使用文件NSFileManager上课时间,创建发现1对象,此2同样的对象地址: NSFileManager *file1=[NSFileManager defaultManager]; ...

  4. Spring.Net控制翻转、依赖注入、面向切面编程

    Spring.Net快速入门:控制翻转.依赖注入.面向切面编程 Spring.Net主要功能: 1.IoC:控制翻转(Inversion of Control)  理解成抽象工厂翻转控制:就是创建对象 ...

  5. 字符串查找KMP算法(转)

    如果你用过ctrl+F这个快捷键,那么你有很大的概率使用过这个算法,这就是在待查找字符串(可能有成千上万个字符)中找出模式串(比较小,可能有几个字符),可能找到大于或者等于1次的位置.例如,在abab ...

  6. hdoj1010Starship Troopers (树dp,依赖背包)

    称号:hdoj1010Starship Troopers 题意:有一个军队n个人要占据m个城市,每一个城市有cap的驻扎兵力和val的珠宝,并且这m个城市的占率先后具有依赖关系,军队的每一个人能够打败 ...

  7. java假设去请求一个网页的数据

    我们能够通过在java程序中模拟浏览器一样,把数据抓下来,详细方法是在java程序中set header和cookie,以下是一个样例: public class NetConnection { pu ...

  8. MEF初体验之六:导出和元素据

    在导出声明这一节中解释了部件导出服务和值的基础知识.在某些情况下,出于多种原因,关联与导出相关的信息是有必要的.通常,它被用来解释一个指定的普通契约实现的能力.这对于允许导入约束满足它的导出,或者导入 ...

  9. linux如果不进入window磁盘

    最近,在windows8.1下安装ubuntu14.04,在windows沉睡.开放时间和进入选择进入系统选项,当时没有引起重视.他选择进入linux系统.但进入后,发现无法进入windows磁盘,百 ...

  10. 基于VMware的虚拟Linux集群搭建-lvs+keepalived

    基于VMware的虚拟Linux集群搭建-lvs+keepalived 本文通过keepalived实现lvsserver的的双机热备和真实server之间的负载均衡.这方面的blog挺多,可是每一个 ...