• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
HaibaraAi
博客园    首页    新随笔    联系   管理    订阅  订阅

FOJ 2013 11 月赛 F

Problem 2137 奇异字符串

Accept: 33    Submit: 149

Time Limit: 1000 mSec    Memory Limit : 32768 KB

我就是个傻逼,虽然这题超时了,但我的时间真的向水一样的丢在上面!

 Problem Description

seen喜欢一种特殊的字符串,seen称这种字符串为奇异字符串。奇异字符串可以表示为AxA这种形式,A为一个任意非空字符串,只包含小写字母,x为一个不在A中出现过的小写字母。seen认为一个长度为d的奇异字符串的价值为d*d,不是奇异字符串的字符串没有价值。现给一个只包含小写字母的字符串,统计其所有子串的价值总和。一个字符串的子串是指其中连续的一段字符构成的字符串。这里相同的子串如果在原串中出现的位置不同则视为不同,需要分别进行统计。

 Input

第一行一个整数T,表示有T组数据。

 

每组数据输入一行只包含小写字母的非空字符串,长度不超过100000。

 Output

对于每组数据输出一行表示所有子串的价值总和。

 Sample Input

1
abcdabc

 Sample Output

49
  1 #include <cstdio>
  2 #include <vector>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 #define maxn 100005
  7 #define INF 0x7fffffff
  8 #define ll long long
  9 ll n,m;
 10 ll ans;
 11 vector<int>g[27];
 12 char s[maxn];
 13 ll sa[maxn], t1[maxn], t2[maxn], c[maxn];
 14 ll rnk[maxn], height[maxn], d[maxn][21],v[maxn];
 15 void RMQ_init(){
 16     for (int i = 0; i < n; i++)d[i][0] = height[i];
 17     for (int j = 1; (1 << j) <= n;j++)
 18     for (int i = 0; i + (1 << j) - 1 < n; i++)
 19         d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
 20 }
 21 int lcp(ll a, ll b){
 22     a = rnk[a]; b = rnk[b];
 23     if (a > b)swap(a, b);
 24     a++;
 25     int t = v[b - a + 1];
 26     return min(d[a][t], d[b-(1<<t)+1][t]);
 27 }
 28 void getheight(){
 29     int i, j, k = 0;
 30     for (i = 0; i < n; i++)rnk[sa[i]] = i;
 31     for (i = 0; i < n; i++){
 32         if (k)k--;
 33         if (rnk[i] - 1 < 0)continue;
 34         int j = sa[rnk[i]-1];
 35         while (s[i + k] == s[j + k])k++;
 36         height[rnk[i]] = k;
 37     }
 38 }
 39 void suffix(int m){
 40     ll  *x = t1, *y = t2;
 41     int i;
 42     for (i = 0; i < m; i++)c[i] = 0;
 43     for (i = 0; i < n; i++)c[x[i] = s[i]-'a']++;
 44     for (i = 1; i < m; i++)c[i] += c[i - 1];
 45     for (i = n - 1; i >= 0; i--)sa[--c[x[i]]] = i;
 46     for (int k = 1; k <= n; ){
 47         int p = 0;
 48         for (i = n - k; i < n; i++)y[p++] = i;
 49         for (i = 0; i < n; i++)if (sa[i] >= k)y[p++] = sa[i] - k;
 50         for (i = 0; i < m; i++)c[i] = 0;
 51         for (i = 0; i < n; i++)c[x[y[i]]]++;
 52         for (i = 1; i < m; i++)c[i] += c[i - 1]; 
 53         for (i = n - 1; i >= 0; i--)sa[--c[x[y[i]]]] = y[i];
 54         swap(x, y);
 55         p = 1; x[sa[0]] = 0;
 56         for (i = 1; i < n; i++)x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
 57         if (p >= n)break;
 58         m = p;
 59         k <<= 1;
 60     }
 61     getheight();
 62 }
 63 ll fun(ll a, ll b){
 64     int x = lcp(a, b);
 65     if (x!=INF&&x>= b - a - 1)return ((b-a)*2-1)*((b-a)*2-1);
 66     return 0;
 67 }
 68 int main(){
 69     int t;
 70     for (int i = 0; i < maxn; i++)
 71         v[i] = (i&(i - 1)) ? v[i - 1] : v[i - 1] + 1;
 72     for (int i = 0; i < maxn; i++)v[i] -= 2;
 73     v[1] = 0; v[2] = v[3] = 1;
 74     scanf("%d", &t);
 75     while (t--){
 76         for (int i = 0; i < 26; i++)g[i].clear();
 77         scanf("%s", s);
 78         n = strlen(s);
 79         m = 0;
 80         ans = 0;
 81         v[0] = -1;
 82         for (int i = 0; i < n; i++)for (int j = 0; i+(1<<j) <= n; j++)d[i][j] = INF;
 83         suffix(26);
 84         RMQ_init();
 85         for (int i = 0; i < n; i++)g[s[i] - 'a'].push_back(i);
 86         for (int i = 0; i < 26; i++){
 87             int d=0;
 88             for (int j = 0; j < g[i].size(); j++){
 89                 if (j == 0 && j == g[i].size() - 1)d = min((ll)g[i][j], n - 1 - g[i][j]);
 90                 else{
 91                     if (j == 0)d = min(g[i][j], g[i][j + 1] - g[i][j]-1);
 92                     else if (j == g[i].size() - 1)d = min((ll)g[i][j] - g[i][j - 1]-1, n - 1 - g[i][j]);
 93                     else d = min(g[i][j] - g[i][j - 1]-1, g[i][j + 1] - g[i][j]-1);
 94                 }
 95                 for (int k = d; k >= 1; k--){
 96                     ll x = 0;
 97                     if (g[i][j] + 1<n)x = fun(g[i][j] - k, g[i][j] + 1);
 98                     if (x > 0){
 99                         ans += x;
100                         k--;
101                     }
102                 }
103             }
104         }
105         printf("%I64d\n", ans);
106     }
107 }
View Code
posted @ 2013-11-19 02:57  HaibaraAi  阅读(145)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3