zoukankan      html  css  js  c++  java
  • hdu 3948 后缀数组

    The Number of Palindromes

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 2465    Accepted Submission(s): 841


    Problem Description
    Now, you are given a string S. We want to know how many distinct substring of S which is palindrome.
     
    Input
    The first line of the input contains a single integer T(T<=20), which indicates number of test cases.
    Each test case consists of a string S, whose length is less than 100000 and only contains lowercase letters.
     
    Output
    For every test case, you should output "Case #k:" first in a single line, where k indicates the case number and starts at 1. Then output the number of distinct substring of S which is palindrome.
     
    Sample Input
    3
    aaaa
    abab
    abcd
     
    Sample Output
    Case #1: 4
    Case #2: 4
    Case #3: 4
    /*
    hdu 3948 后缀数组
    
    problem:
    给你一个字符串,问其中不同回文子串的个数
    
    solve:
    通过长度的奇偶性能够找出所有的回文子串(类似求最长回文子串),但是其中有很多重复的一直不知道怎么处理
    有的较短的回文子串包含在一个长的里面,有的是两个回文有重复的部分。
    最开始尝试的是通过枚举字符串所有的位置,类似于manacher求出所有位置的回文长度.但是发现完全没法解决重复的问题
    
    参考别人的方法:
    首先height数组可以知道两个回文子串的关系,所以枚举height.
    通过ta记录当前位置与上一个回文串的公共前缀,当遇到下个回文串就能知道两个回文串的公共部分.即需要减去的重复部分
    ta = min(ta,height[i]);
    而且枚举height不知道当前回文串是否处理过,所以用vis记录一下
    
    hhh-2016-08-11 13:51:03
    */
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <functional>
    #include <map>
    using namespace std;
    #define lson  (i<<1)
    #define rson  ((i<<1)|1)
    typedef long long ll;
    typedef unsigned int ul;
    const int INF = 0x3f3f3f3f;
    const int  maxn = 200000+10;
    const int mod = 1e9+7;
    
    int t1[maxn],t2[maxn],c[maxn];
    bool cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b] &&r[l+a] == r[l+b];
    }
    
    void get_sa(int str[],int sa[],int Rank[],int height[],int n,int m)
    {
        n++;
        int p,*x=t1,*y=t2;
        for(int i = 0; i < m; i++) c[i] = 0;
        for(int i = 0; i < n; i++) c[x[i] = str[i]]++;
        for(int i = 1; i < m; i++) c[i] += c[i-1];
        for(int i = n-1; i>=0; i--) sa[--c[x[i]]] = i;
        for(int j = 1; j <= n; j <<= 1)
        {
            p = 0;
            for(int i = n-j; i < n; i++) y[p++] = i;
            for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j;
            for(int i = 0; i < m; i++) c[i] = 0;
            for(int i = 0; i < n; i++) c[x[y[i]]]++ ;
            for(int i = 1; i < m; i++) c[i] += c[i-1];
            for(int i = n-1; i >= 0; i--)  sa[--c[x[y[i]]]] = y[i];
    
            swap(x,y);
            p = 1;
            x[sa[0]] = 0;
            for(int i = 1; i < n; i++)
                x[sa[i]] = cmp(y,sa[i-1],sa[i],j)? p-1:p++;
            if(p >= n) break;
            m = p;
        }
        int k = 0;
        n--;
        for(int i = 0; i <= n; i++)
            Rank[sa[i]] = i;
        for(int i = 0; i < n; i++)
        {
            if(k) k--;
            int j = sa[Rank[i]-1];
            while(str[i+k] == str[j+k]) k++;
            height[Rank[i]] = k;
        }
    
    }
    
    int mm[maxn];
    int dp[20][maxn];
    
    int Rank[maxn],height[maxn];
    int sa[maxn];
    char str[maxn];
    int r[maxn];
    
    void ini_RMQ(int n)
    {
        mm[0] = -1;
        for(int i = 1; i <= n; i++)
            mm[i] = (((i & (i-1)) == 0) ? mm[i-1]+1:mm[i-1]);
    
        for(int i =1; i <= n; i++)
            dp[0][i] = height[i];
        for(int i = 1; i <= mm[n]; i++)
        {
            for(int j = 1; j+(1<<i)-1 <= n; j++)
            {
                int a = dp[i-1][j];
                int b = dp[i-1][j+(1<<(i-1))];
                dp[i][j] = min(a,b);
            }
        }
    }
    
    int askRMQ(int a,int b)
    {
        int t = mm[b-a+1];
        b -= (1<<t)-1;
        return min(dp[t][a],dp[t][b]);
    }
    
    
    int fin(int a,int b)
    {
        a = Rank[a],b = Rank[b];
        if(a > b) swap(a,b);
        return askRMQ(a+1,b);
    }
    int vis[maxn];
    
    int main()
    {
        int T;
        int cas = 1;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%s",str);
            int len = strlen(str);
            for(int i= 0; i < len; i++)
                r[i] = str[i];
            r[len] = 1;
            for(int i = 0; i < len; i++)
                r[len+1+i] = str[len-1-i];
            r[2*len+1] = 0;
            get_sa(r,sa,Rank,height,len*2+1,128);
            ini_RMQ(2*len+1);
            int ans = 0;
            int n = len+len+1;
            int ta=0;
            memset(vis,0,sizeof(vis));
            for(int i = 2; i <= n; i++)
            {
                ta = min(height[i],ta);
                if(!sa[i])
                    continue;
                if(vis[n-sa[i]])
                {
                    int t = fin(sa[i],n-sa[i]);
                    if(t > ta)
                    {
                        ans += t-ta;
                        ta = t;
                    }
                }
                else
                    vis[sa[i]] = 1;
            }
            ta= 0 ;
            memset(vis,0,sizeof(vis));
            for(int i = 2; i <= n; i++)
            {
                ta= min(ta,height[i]);
                if(vis[n-sa[i]-1])
                {
                    int t = fin(sa[i],n-sa[i]-1);
                    if(t > ta)
                    {
                        ans += t-ta;
                        ta = t;
                    }
                }
                else
                    vis[sa[i]] = 1;
            }
            printf("Case #%d: ",cas++);
            printf("%d
    ",ans);
        }
    }
    

      

  • 相关阅读:
    javascript优化--10模式(设计模式)01
    javascript优化--09模式(代码复用)02
    限制字符个数显示
    title
    点选词高亮算法
    ng-repeat嵌套的$index
    console.log的问题
    outsideClick 功能,探索
    input 框的 placeholder 另类实现
    ie9 与 placeholder 问题
  • 原文地址:https://www.cnblogs.com/Przz/p/5792173.html
Copyright © 2011-2022 走看看