题意:给你一个字符串和m个询问,问你l,r这个区间内出现过多少字串。

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

网上也有用后缀数组搞得、

思路(虎哥):用字典树把每一个字符串对应成一个整数 相同的字符串对应到相同的整数上

把所用的串对应的整数放在一个数组里 比如书字符串s[l...r]对应的整数是 k

那么二维数组 [l][r] 就等于k

假设一个对应好的二维数组  左下角是原点

3     4     5     2

2     3     4     0

1     6     0     0

2     0     0     0

这样求解 从l到r的不同字符串的个数 其实就是求 从[l][r] 到右下角所在的矩阵所包含不同整数的个数(不包括0)

这里需要一定的去重处理 处理后是

-1    0    1     1

0     1    1     0

1     1    0     0

1     0    0     0

然后一边dp就可以求出所有答案(因为是求一个矩形矩阵,所以我用了一个二维树状数组做的,感觉好慢- -。)

注意常用的next[26]写法的字典树有可能超内存 要优化

代码:

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <queue>
#define loop(s,i,n) for(i = s;i < n;i++)
#define cl(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x&-x
using namespace std; const int maxm = ;
const int maxn = ; int head[maxm]; struct node
{
int next,v;
}g[maxm]; int cnt;
int c[maxn][maxn];
int pos[maxm];
char s[maxn];
int len;
void add(int a,int b,int val)
{
int i,j;
for(i = a;i <= len;i += lowbit(i))
{
for(j = b;j <= len;j += lowbit(j))
c[i][j] += val;
}
} int sum(int a,int b)
{
int res = ;
int i,j;
for(i = a;i > ;i -= lowbit(i))
{
for(j = b;j > ;j -= lowbit(j))
res+=c[i][j];
}
return res;
}
void insert(int &u,int key)
{
int i;
for(i = head[u];i != -;i = g[i].next)
{
int v;
v = g[i].v;
if(v == key)
{
u = i;
return ;
}
}
cnt++;
g[cnt].next = head[u];
g[cnt].v = key;
head[u] = cnt;
u = cnt;
return ;
}
int main()
{
int t;
//freopen("out.txt","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%s",s);
len = strlen(s);
cl(c,);
cl(pos,-);
cl(head,-);
int j,i,loc;
loc = ;
cnt = ;
loop(,j,len)
{
loc = ;
for(i = j;i >= ;--i)
{
int key = s[i]-'a'; insert(loc,key); if(pos[loc] == -)
{
add(i+,j+,);
pos[loc] = i+;
}
else if(pos[loc] < (i+))
{
add(i+,j+,);
add(pos[loc],j+,-);
pos[loc] = i+;
}
}
}
int m,l,r;
scanf("%d",&m);
while(m--)
{
scanf("%d %d",&l,&r);
printf("%d\n",sum(l-,)+sum(len,r)-sum(l-,r)-sum(len,));
} }
return ;
}

这个是dp的。

 #include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
struct list
{
int next;
int v;
}g[];
int head[];
int vis[];
int ct;
char str[];
int c[][];
void add(int x,int &u)
{
for(int i=head[u];i!=-;i=g[i].next)
{
if(x==g[i].v)
{
u=i;return ;
}
}
g[ct].next=head[u];
g[ct].v=x;
head[u]=ct;
u=ct++;
}
int main()
{
int n,p;
int T,i,j;
scanf("%d%*c",&T);
while(T--)
{
ct=;
memset(head,-,sizeof(head));
memset(vis,-,sizeof(vis));
memset(c,,sizeof(c));
gets(str);
n=strlen(str);
for(j=;j<n;j++)
{
p=;
for(i=j;i>=;i--)
{
add(str[i],p);
if(vis[p]==-)
{
vis[p]=i;
c[i][j]++;
}
else if(vis[p]<i)
{
c[i][j]++;
c[vis[p]][j]--;
vis[p]=i;
}
}
}
// for(j=1;j<n;j++)c[0][j]+=c[0][j-1];
for(j=;j<n;j++)
{
for(i=j;i>=;i--)
{
c[i][j]+=c[i+][j]+c[i][j-]-c[i+][j-];
}
}
int q,a,b;
cin>>q;
while(q--)
{
scanf("%d%d%*c",&a,&b);
printf("%d\n",c[a-][b-]);
}
}
return ;
}

hdu 4622 Reincarnation trie树+树状数组/dp的更多相关文章

  1. hdu 4622 Reincarnation(后缀数组)

    hdu 4622 Reincarnation 题意:还是比较容易理解,给出一个字符串,最长2000,q个询问,每次询问[l,r]区间内有多少个不同的字串. (为了与论文解释统一,这里解题思路里sa数组 ...

  2. HDU 4622 Reincarnation Hash解法详解

    今天想学字符串hash是怎么弄的.就看到了这题模板题 http://acm.hdu.edu.cn/showproblem.php?pid=4622 刚开始当然不懂啦,然后就上网搜解法.很多都是什么后缀 ...

  3. 【树状数组+dp】HDU 5542 The Battle of Chibi

    http://acm.hdu.edu.cn/showproblem.php?pid=5542 [题意] 给定长为n的序列,问有多少个长为m的严格上升子序列? [思路] dp[i][j]表示以a[i]结 ...

  4. HDU 1166 敌兵布阵 (数状数组,或线段树)

    题意:... 析:可以直接用数状数组进行模拟,也可以用线段树. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&quo ...

  5. HDU 6348 序列计数 (树状数组 + DP)

    序列计数 Time Limit: 4500/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Subm ...

  6. hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

    Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java ...

  7. hdu 2227(树状数组+dp)

    Find the nondecreasing subsequences Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/3 ...

  8. HDU 6447 YJJ’s Salesman (树状数组 + DP + 离散)

    题意: 二维平面上N个点,从(0,0)出发到(1e9,1e9),每次只能往右,上,右上三个方向移动, 该N个点只有从它的左下方格点可达,此时可获得收益.求该过程最大收益. 分析:我们很容易就可以想到用 ...

  9. hdu 4991(树状数组+DP)

    Ordered Subsequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

随机推荐

  1. HTML5程序设计--SVG

    SVG(Scalable Vector Graphics):可缩放矢量图形,一种二维图形表示语言. 借助SVG,我们可以实现很多同Canvas API类型的绘制操作,但在Canvas元素上绘制文本的时 ...

  2. NSArray block用法

    28.使用block 块遍历整个数组.这个block 需要三个参数,id obj 表示数组中的元素. NSUInteger idx 标示元素的下标, bool *stop 是一个bool类型的参数. ...

  3. [C++]iostream的几种输入形式

    做ACM题的时候,发现cin并不能满足所有输入要求.比如说: 每行给出一款运动鞋信息,若该款写不打折,则先后给出每种运动鞋单价P,所购买的数量Q:若打折,则先后给出每种运动鞋单价P,所购买的数量Q,折 ...

  4. ==和equals的区别

    == :是判断两个变量或实例是不是指向同一个内存空间equals :是判断两个变量或实例所指向的内存空间的值是不是相同 结论:欲比较栈中数据是否相等,请用= =:欲比较堆中数据是否相等,请用equal ...

  5. POJ 3335 Rotating Scoreboard(半平面交求多边形核)

    题目链接 题意 : 给你一个多边形,问你在多边形内部是否存在这样的点,使得这个点能够看到任何在多边形边界上的点. 思路 : 半平面交求多边形内核. 半平面交资料 关于求多边形内核的算法 什么是多边形的 ...

  6. Linux搜狗输入法在有道云笔记上输入冗余

    Linux下,在有道云笔记中用搜狗拼音输入法时,会出现输入冗余,类似于输入法的缓冲上屏了.这是有道云笔记Web页面的问题. 暂时的解决办法是按Ctrl + alt + p. 不仅搜狗输入法,凡是用fc ...

  7. hdu 1515 Anagrams by Stack

    题解: 第一:两个字符不相等(即栈顶字符与目标字符不相等):这种情况很容易处理,将匹配word的下一个字符入栈,指针向后挪已为继续递归. 第二:两个字符相等(即栈顶字符与目标字符相等):这种情况有两种 ...

  8. linux下修改tomcat的默认目录

    1.修改tomcat的默认目录.它的默认目录是webapps/ROOT,对应的conf目录下的server.xml里的内容是: 1.修改tomcat的默认目录.它的默认目录是webapps/ROOT, ...

  9. PHP组合模式、策略模式

    一.问题 模拟不同课程有不同的收费方式,并且能灵活改变(新增或删减),如讲座可以固定收费也可改为按时收费,研讨会也是. 二.模式简介及关键点 1.在父类代码中使用条件语句是一种退倒,可以用多态来代替条 ...

  10. Struts2笔记——通配符和动态方法调用

     通配符映射 * 一个 Web应用可能有成百上千个 action 声明. 可以利用 struts提供的通配符映射机制把多个彼此相似的映射关系简化为一个映射关系 * 通配符映射规则     > 若 ...