HDU 4622 求解区间字符串中的不同子串的个数

题目大意:

给定一个长度<2000的串,再给最多可达10000的询问区间,求解区间字符串中的不同子串的个数

这里先考虑求解一整个字符串的所有不同子串的方法

对于后缀自动机来说,我们动态往里添加一个字符,每次添加一个字符进去,我们只考虑那个生成的长度为当前长度的后缀自动机的节点

那么这个节点可接收的字符串的个数就是( p->l - p->f->l ),也就是以当前点为最后节点所能得到的与之前不重复的子串的个数

那么这个问题就很好解决了,共2000个位置,以每一个位置为起点构建一次后缀自动机,一直构建到最后一个字符,过程中不断记录所能得到的子串个数

把这个个数动态保存到f[][]数组中

那么打好了表,最后询问的时候,直接访问这个f[][]即可

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5
 6 using namespace std;
 7 #define N 2005
 8 #define M 26
 9 struct SamNode{
10     SamNode *son[M] , *f;
11     int l;
12     void init(){
13         for(int i=0 ; i<M ; i++) son[i] = NULL;
14         f=NULL , l=0;
15     }
16 }sam[N<<1] , *root , *last;
17
18 int cnt , f[N][N] , ret;
19 char s[N] ;
20
21 void init(){
22     sam[0].init();
23     root = last = &sam[cnt=0];
24 }
25
26 void add(int x)
27 {
28     SamNode *p = &sam[++cnt] , *jp=last;
29     p->init();
30     p->l = jp->l+1;
31     last = p;
32     for(; jp&&!jp->son[x] ; jp=jp->f) jp->son[x] = p;
33     if(!jp) p->f = root;
34     else{
35         if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x];
36         else{
37             SamNode *r = &sam[++cnt] , *q = jp->son[x];
38             r->init();
39             *r = *q; r->l = jp->l+1;
40             p->f = q->f = r;
41             for( ; jp&&jp->son[x]==q ; jp=jp->f) jp->son[x] = r;
42         }
43     }
44     ret += p->l-(p->f->l);
45 }
46
47 void solve()
48 {
49     int len = strlen(s);
50     for(int i=0 ; i<len ; i++){
51         ret = 0;
52         init();
53         for(int j=i ; j<len ; j++){
54             add(s[j]-‘a‘);
55             f[i][j] = ret;
56         }
57     }
58 }
59
60 int main()
61 {
62   //  freopen("a.in" , "r" , stdin);
63     int T;
64     scanf("%d" , &T);
65     while(T--)
66     {
67         scanf("%s", s);
68         int m , l , r;
69         scanf("%d" , &m);
70         solve();
71         while(m--){
72             scanf("%d%d" , &l , &r);
73             printf("%d\n" , f[l-1][r-1]);
74         }
75     }
76     return 0;
77 }
时间: 2024-10-13 22:00:11

HDU 4622 求解区间字符串中的不同子串的个数的相关文章

寻找Coder-统计一个字符串中另外一个子串的个数

题目描述 请设计一个高效算法,再给定的字符串数组中,找到包含"Coder"的字符串(不区分大小写),并将其作为一个新的数组返回.结果字符串的顺序按照"Coder"出现的次数递减排列,若两个串中"Coder"出现的次数相同,则保持他们在原数组中的位置关系. 给定一个字符串数组A和它的大小n,请返回结果数组.保证原数组大小小于等于300,其中每个串的长度小于等于200.同时保证一定存在包含coder的字符串. 测试样例: ["i am a

获取两个字符串中最大相同子串

2.获取两个字符串中最大相同子串.第一个动作:将短的那个串进行长度一次递减的子串打印. "cvhellobnmtanop" "andefc" 思路: 1,将短的那个子串按照长度递减的方式获取到. 2,将每获取到的子串去长串中判断是否包含,如果包含,已经找到! package tan; class Test { public static String getMaxSubString(String s1,String s2) { String max = "

10:字符串中含有某个字符的个数

题目描述:写出一个程序,接受一个有字母和数字以及空格组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数.不区分大小写. 输入描述:输入一个有字母和数字以及空格组成的字符串,和一个字符. 输出描述:输出输入字符串中含有该字符的个数. 输入例子: ABCDEF A 输出例子:1 package prctice01; import java.util.Scanner; /*题目描述:写出一个程序,接受一个有字母和数字以及空格组成的字符串,和一个字符,然后输出输入字符串中含有该字符的个数.不

AutoLisp 返回字符串中某一子串首次出现的位置的函数

1 ;返回字符串中某一子串首次出现的位置 2 (defun my_strstr(mstr zstr / retu) 3 (setq mstr_l (strlen mstr) zstr_l (strlen zstr)) 4 (if (<= zstr_l mstr_l) 5 ;主字符串长度大于或等于子字符长度 6 (progn 7 (setq i 1) 8 (setq tc_w1 T) ;退出循环时使用 9 (setq ppqk nil) ;表示匹配情况 10 (while (and tc_w1 (

查找字符串中最长子串

查找字符串中最长子串,例如“I love OC”最长子串为“love” 1 void findMaxLengthSubstr1(char *src) 2 { 3 char *start = src; 4 char *end = src; 5 unsigned int maxLength = 0; 6 unsigned int tempLength = 0; 7 // 此处子串长度不能超过100 8 char maxStr[100] = "0"; 9 10 if (src == NULL

黑马程序员——找出两个字符串中最大的子串

找出两个字符串中最大的子串 </pre><pre name="code" class="java">public class StringMaxString { //找一个字符串的最大子串 public static void main(String[] args) { // TODO Auto-generated method stub String s1="qwerabcdtyuiop"; String s2=&quo

统计字符串中,各个字符的个数(回炉练习)

__author__ = 'ZHHT' #!/usr/bin/env python # -*- coding:utf-8 -*- #统计字符串中,各个字符的个数 #比如:"hello world" 字符串统计的结果为: h:1 e:1 l:3 o:2 d:1 r:1 w:1 a = "hello world" b = set(a) for i in b: if i == ' ': c = a.count(i) i = '空格' print("%s出现%d次

POJ 3294 二分找超过一半字符串中存在的子串

题目大意: 给定n个字符串,求出现在不小于k/2个字符串中的最长子串. 二分找对应子串长度的答案,将所有字符串链接成一个长字符串求后缀数组,记录每一个位置本属于第几个字符串,利用height查询的时候, 根据记录的位置不断判断是否出现重复的字符串是在同一个字符串内的 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <iostream> 5 using namesp

萌新笔记——Cardinality Estimation算法学习(一)(了解基数计算的基本概念及回顾求字符串中不重复元素的个数的问题)

最近在菜鸟教程上自学redis.看到Redis HyperLogLog的时候,对"基数"以及其它一些没接触过(或者是忘了)的东西产生了好奇. 于是就去搜了"HyperLogLog",从而引出了Cardinality Estimation算法,以及学习它时参考的一些文章: http://blog.codinglabs.org/articles/algorithms-for-cardinality-estimation-part-i.html 从文章上看来,基数是指一个