• hdu 4622 Reincarnation trie树+树状数组/dp


    题意:给你一个字符串和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]写法的字典树有可能超内存 要优化

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <stdlib.h>
      6 #include <vector>
      7 #include <queue>
      8 #define loop(s,i,n) for(i = s;i < n;i++)
      9 #define cl(a,b) memset(a,b,sizeof(a))
     10 #define lowbit(x) x&-x
     11 using namespace std;
     12 
     13 const int maxm = 2000000;
     14 const int maxn = 2007;
     15 
     16 int head[maxm];
     17 
     18 struct node
     19 {
     20     int next,v;
     21 }g[maxm];
     22 
     23 int cnt;
     24 int c[maxn][maxn];
     25 int pos[maxm];
     26 char s[maxn];
     27 int len;
     28 void add(int a,int b,int val)
     29 {
     30     int i,j;
     31     for(i = a;i <= len;i += lowbit(i))
     32     {
     33         for(j = b;j <= len;j += lowbit(j))
     34         c[i][j] += val;
     35     }
     36 }
     37 
     38 int sum(int a,int b)
     39 {
     40     int res = 0;
     41     int i,j;
     42     for(i = a;i > 0;i -= lowbit(i))
     43     {
     44         for(j = b;j > 0;j -= lowbit(j))
     45         res+=c[i][j];
     46     }
     47     return res;
     48 }
     49 void insert(int &u,int key)
     50 {
     51     int i;
     52     for(i = head[u];i != -1;i = g[i].next)
     53     {
     54         int v;
     55         v = g[i].v;
     56         if(v == key)
     57         {
     58             u = i;
     59             return ;
     60         }
     61     }
     62     cnt++;
     63     g[cnt].next = head[u];
     64     g[cnt].v = key;
     65     head[u] = cnt;
     66     u = cnt;
     67     return ;
     68 }
     69 int main()
     70 {
     71     int t;
     72     //freopen("out.txt","w",stdout);
     73     scanf("%d",&t);
     74     while(t--)
     75     {
     76         scanf("%s",s);
     77         len = strlen(s);
     78         cl(c,0);
     79         cl(pos,-1);
     80         cl(head,-1);
     81         int j,i,loc;
     82         loc = 0;
     83         cnt = 0;
     84         loop(0,j,len)
     85         {
     86             loc = 0;
     87             for(i = j;i >= 0;--i)
     88             {
     89                 int key = s[i]-'a';
     90 
     91                 insert(loc,key);
     92 
     93                 if(pos[loc] == -1)
     94                 {
     95                     add(i+1,j+1,1);
     96                     pos[loc] = i+1;
     97                 }
     98                 else if(pos[loc] < (i+1))
     99                 {
    100                     add(i+1,j+1,1);
    101                     add(pos[loc],j+1,-1);
    102                     pos[loc] = i+1;
    103                 }
    104             }
    105         }
    106         int m,l,r;
    107         scanf("%d",&m);
    108         while(m--)
    109         {
    110             scanf("%d %d",&l,&r);
    111             printf("%d
    ",sum(l-1,0)+sum(len,r)-sum(l-1,r)-sum(len,0));
    112         }
    113 
    114     }
    115     return 0;
    116 }
    View Code

    这个是dp的。

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<string.h>
     5 using namespace std;
     6 struct list
     7 {
     8     int next;
     9     int v;
    10 }g[2000001];
    11 int head[2000001];
    12 int vis[2000001];
    13 int ct;
    14 char str[3001];
    15 int c[2001][2001];
    16 void add(int x,int &u)
    17 {
    18     for(int i=head[u];i!=-1;i=g[i].next)
    19     {
    20         if(x==g[i].v)
    21         {
    22             u=i;return ;
    23         }
    24     }
    25     g[ct].next=head[u];
    26     g[ct].v=x;
    27     head[u]=ct;
    28     u=ct++;
    29 }
    30 int main()
    31 {
    32     int n,p;
    33     int T,i,j;
    34     scanf("%d%*c",&T);
    35     while(T--)
    36     {
    37         ct=1;
    38         memset(head,-1,sizeof(head));
    39         memset(vis,-1,sizeof(vis));
    40         memset(c,0,sizeof(c));
    41         gets(str);
    42         n=strlen(str);
    43         for(j=0;j<n;j++)
    44         {
    45             p=0;
    46             for(i=j;i>=0;i--)
    47             {
    48                 add(str[i],p);
    49                 if(vis[p]==-1)
    50                 {
    51                     vis[p]=i;
    52                     c[i][j]++;
    53                 }
    54                 else if(vis[p]<i)
    55                 {
    56                     c[i][j]++;
    57                     c[vis[p]][j]--;
    58                     vis[p]=i;
    59                 }
    60             }
    61         }
    62     //    for(j=1;j<n;j++)c[0][j]+=c[0][j-1];
    63         for(j=1;j<n;j++)
    64         {
    65             for(i=j;i>=0;i--)
    66             {
    67                 c[i][j]+=c[i+1][j]+c[i][j-1]-c[i+1][j-1];
    68             }
    69         }
    70         int q,a,b;
    71         cin>>q;
    72         while(q--)
    73         {
    74             scanf("%d%d%*c",&a,&b);
    75             printf("%d
    ",c[a-1][b-1]);
    76         }
    77     }
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    【原】如何实现IE6下块级元素的内容自动收缩
    【原】常见的模块,你语义化了没
    【转】CSS Nuggest
    那年,寻找工作的历程
    前端开发小工具SuperApp——Ctrl+S自动刷新浏览器
    【转】在html中引入CSS的方法
    HTML中常用的实体字符
    imemode:disabled 禁止表单使用文本框输入法
    【原】工作中常用win7快捷键
    复制本地文件完整路径
  • 原文地址:https://www.cnblogs.com/0803yijia/p/3234241.html
Copyright © 2020-2023  润新知