【HDOJ】3948 The Number of Palindromes

后缀数组求不重复回文子串数目。注意dp数组。

  1 /* 3948 */
  2 #include <iostream>
  3 #include <sstream>
  4 #include <string>
  5 #include <map>
  6 #include <queue>
  7 #include <set>
  8 #include <stack>
  9 #include <vector>
 10 #include <deque>
 11 #include <algorithm>
 12 #include <cstdio>
 13 #include <cmath>
 14 #include <ctime>
 15 #include <cstring>
 16 #include <climits>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <functional>
 20 #include <iterator>
 21 #include <iomanip>
 22 using namespace std;
 23 //#pragma comment(linker,"/STACK:102400000,1024000")
 24 
 25 #define sti                set<int>
 26 #define stpii            set<pair<int, int> >
 27 #define mpii            map<int,int>
 28 #define vi                vector<int>
 29 #define pii                pair<int,int>
 30 #define vpii            vector<pair<int,int> >
 31 #define rep(i, a, n)     for (int i=a;i<n;++i)
 32 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 33 #define clr                clear
 34 #define pb                 push_back
 35 #define mp                 make_pair
 36 #define fir                first
 37 #define sec                second
 38 #define all(x)             (x).begin(),(x).end()
 39 #define SZ(x)             ((int)(x).size())
 40 #define lson            l, mid, rt<<1
 41 #define rson            mid+1, r, rt<<1|1
 42 
 43 const int INF = 0x3f3f3f3f;
 44 const int maxl = 2e5+5;
 45 const int maxn = 4e5+5;
 46 char s[maxl], ss[maxl];
 47 int a[maxn];
 48 int height[maxn], rrank[maxn], sa[maxn];
 49 int wa[maxn], wb[maxn], wc[maxn], wv[maxn];
 50 bool visit[maxn];
 51 int dp[19][maxn];
 52 
 53 bool cmp(int *r, int a, int b, int l) {
 54     return r[a]==r[b] && r[a+l]==r[b+l];
 55 }
 56 
 57 void da(int *r, int *sa, int n, int m) {
 58     int i, j, *x=wa, *y=wb, *t, p;
 59 
 60     for (i=0; i<m; ++i) wc[i] = 0;
 61     for (i=0; i<n; ++i) wc[x[i]=r[i]]++;
 62     for (i=1; i<m; ++i) wc[i] += wc[i-1];
 63     for (i=n-1; i>=0; --i) sa[--wc[x[i]]]=i;
 64     for (j=1,p=1; p<n; j*=2, m=p) {
 65         for (p=0,i=n-j; i<n; ++i) y[p++] = i;
 66         for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
 67         for (i=0; i<n; ++i) wv[i] = x[y[i]];
 68         for (i=0; i<m; ++i) wc[i] = 0;
 69         for (i=0; i<n; ++i) wc[wv[i]]++;
 70         for (i=1; i<m; ++i) wc[i] += wc[i-1];
 71         for (i=n-1; i>=0; --i) sa[--wc[wv[i]]] = y[i];
 72         for (t=x,x=y,y=t, x[sa[0]]=0, p=1,i=1; i<n; ++i)
 73             x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1:p++;
 74     }
 75 }
 76 
 77 void calheight(int *r, int *sa, int n) {
 78     int i, j, k = 0;
 79 
 80     for (i=1; i<=n; ++i) rrank[sa[i]] = i;
 81     for (i=0; i<n; height[rrank[i++]]=k)
 82     for (k?k--:0, j=sa[rrank[i]-1]; r[i+k]==r[j+k]; ++k) ;
 83 }
 84 
 85 void printSa(int n) {
 86     for (int i=1; i<=n; ++i)
 87         printf("%d ", sa[i]);
 88     putchar('\n');
 89 }
 90 
 91 void printHeight(int n) {
 92     for (int i=1; i<=n; ++i)
 93         printf("%d ", height[i]);
 94     putchar('\n');
 95 }
 96 
 97 void printRank(int n) {
 98     for (int i=1; i<=n; ++i)
 99         printf("%d ", rrank[i]);
100     putchar('\n');
101 }
102 
103 void init_RMQ(int n) {
104     int i, j;
105 
106     for (i=1; i<=n; ++i)
107         dp[0][i] = height[i];
108     dp[0][1] = INF;
109     for (j=1; (1<<j)<=n; ++j)
110         for (i=1; i+(1<<j)-1<=n; ++i)
111             dp[j][i] = min(dp[j-1][i], dp[j-1][i+(1<<(j-1))]);
112 }
113 
114 int RMQ(int l, int r) {
115     if (l > r)
116         swap(l, r);
117 
118     ++l;
119     int k = 0;
120 
121     while (1<<(k+1) <= r-l+1)
122         ++k;
123 
124     return min(dp[k][l], dp[k][r-(1<<k)+1]);
125 }
126 
127 void solve() {
128     int len = strlen(s);
129     int nn = len * 2 + 1, n, nn2 = nn * 2;
130     int l = 0;
131 
132     rep(i, 0, len) {
133         a[l] = a[nn2-l] = 2;
134         ++l;
135         a[l] = a[nn2-l] = s[i]-'a'+3;
136         ++l;
137     }
138     a[l] = a[nn2-l] = 2;
139     a[nn] = 1;
140     a[nn2+1] = 0;
141 
142     n = nn2 + 1;
143     da(a, sa, n+1, 32);
144     calheight(a, sa, n);
145     
146     #ifndef ONLINE_JUDGE
147         // printSa(n);
148         // printHeight(n);
149     #endif
150 
151     init_RMQ(n);
152 
153     int ans = 0, mn = 0, tmp;
154 
155     memset(visit, false, sizeof(visit));
156     rep(i, 2, n+1) {
157         mn = min(mn, height[i]);
158         if (visit[nn2-sa[i]]) {
159             tmp = RMQ(rrank[sa[i]], rrank[nn2-sa[i]]);
160             if (tmp > mn) {
161                 ans += (tmp - mn) >> 1;
162                 mn = tmp;
163             }
164         } else {
165             visit[sa[i]] = true;
166         }
167     }
168 
169     printf("%d\n", ans);
170 }
171 
172 int main() {
173     ios::sync_with_stdio(false);
174     #ifndef ONLINE_JUDGE
175         freopen("data.in", "r", stdin);
176         freopen("data.out", "w", stdout);
177     #endif
178 
179     int t;
180 
181     scanf("%d", &t);
182     rep(tt, 1, t+1) {
183         scanf("%s", s);
184         printf("Case #%d: ", tt);
185         solve();
186     }
187 
188     #ifndef ONLINE_JUDGE
189         printf("time = %d.\n", (int)clock());
190     #endif
191 
192     return 0;
193 }

数据生成器。

 1 from random import randint, shuffle
 2 import shutil
 3 import string
 4 
 5 
 6 def GenDataIn():
 7     with open("data.in", "w") as fout:
 8         t = 20
 9         bound = 10**3
10         lc = list(string.lowercase)
11         fout.write("%d\n" % (t))
12         for tt in xrange(t):
13             length = randint(50, 105)
14             line = ""
15             for i in xrange(length):
16                 idx = randint(0, 5)
17                 line += lc[idx]
18             fout.write("%s\n" % (line))
19             
20         
21                 
22 def MovDataIn():
23     desFileName = "F:\eclipse_prj\workspace\hdoj\data.in"
24     shutil.copyfile("data.in", desFileName)
25 
26     
27 if __name__ == "__main__":
28     GenDataIn()
29     MovDataIn()

 

转载于:https://www.cnblogs.com/bombe1013/p/5180829.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值