zoukankan      html  css  js  c++  java
  • Codeforces Round #246 (Div. 2) D. Prefixes and Suffixe 后缀数组

    链接:

    codeforces.com/contest/432/problem/D

    题意:

    给你一个字符串,求每一个和前缀匹配的后缀在这个字符串中出现的次数

    题解:

    先算出lcp,找到sa[i]==0的位置标记为beg,和前缀匹配的后缀一定会出现beg的左边,这个想一想明白了

    我们先算出beg左边每一个后缀和beg匹配的长度,beg右边的先放到一个vector中,便于之后二分查找

    我们从beg向左遍历,对于每一个dp[i],如果dp[i]==n-sa[i],就可以更新结果了,从i到beg中间的都满足,同时还要加上beg右边的

    代码:

     31 int n, k;
     32 int Rank[MAXN], tmp[MAXN];
     33 int sa[MAXN], lcp[MAXN];
     34 
     35 bool compare_sa(int i, int j) {
     36     if (Rank[i] != Rank[j]) return Rank[i] < Rank[j];
     37     else {
     38         int ri = i + k <= n ? Rank[i + k] : -1;
     39         int rj = j + k <= n ? Rank[j + k] : -1;
     40         return ri < rj;
     41     }
     42 }
     43 
     44 void construct_sa(string S, int *sa) {
     45     n = S.length();
     46     for (int i = 0; i <= n; i++) {
     47         sa[i] = i;
     48         Rank[i] = i < n ? S[i] : -1;
     49     }
     50     for (k = 1; k <= n; k *= 2) {
     51         sort(sa, sa + n + 1, compare_sa);
     52         tmp[sa[0]] = 0;
     53         for (int i = 1; i <= n; i++)
     54             tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
     55         for (int i = 0; i <= n; i++) Rank[i] = tmp[i];
     56     }
     57 }
     58 
     59 void construct_lcp(string S, int *sa, int *lcp) {
     60     int n = S.length();
     61     for (int i = 0; i <= n; i++) Rank[sa[i]] = i;
     62     int h = 0;
     63     lcp[0] = 0;
     64     for (int i = 0; i < n; i++) {
     65         int j = sa[Rank[i] - 1];
     66         if (h > 0) h--;
     67         for (; j + h < n && i + h < n; h++)
     68             if (S[j + h] != S[i + h]) break;
     69         lcp[Rank[i] - 1] = h;
     70     }
     71 }
     72 
     73 int dp[MAXN];
     74 
     75 int main() {
     76     ios::sync_with_stdio(false), cin.tie(0);
     77     string s;
     78     cin >> s;
     79     construct_sa(s, sa);
     80     construct_lcp(s, sa, lcp);
     81     int beg;
     82     rep(i, 0, n + 1) if (sa[i] == 0) {
     83         beg = i;
     84         break;
     85     }
     86     memset(dp, 0x3f, sizeof(dp));
     87     dp[beg] = INF;
     88     per(i, 0, beg) dp[i] = min(dp[i + 1], lcp[i]);
     89     rep(i, beg + 1, n + 1) dp[i] = min(dp[i - 1], lcp[i - 1]);
     90     VI v;
     91     rep(i, beg + 1, n + 1) if (dp[i]) v.pb(dp[i]);
     92     sort(all(v));
     93     map<int, int> mmp;
     94     per(i, 0, beg) {
     95         if (!dp[i]) break;
     96         if (dp[i] == n - sa[i]) {
     97             mmp[dp[i]] += beg - i + 1;
     98             mmp[dp[i]] += v.end() - lower_bound(all(v), dp[i]);
     99         }
    100     }
    101     cout << mmp.size() + 1 << endl;
    102     for (auto it : mmp) cout << it.first << ' ' << it.second << endl;
    103     cout << n << ' ' << 1 << endl;
    104     return 0;
    105 }
  • 相关阅读:
    对技术的研究就是对世界的理解
    程序员的方向
    程序员的分类
    设置tomcat的catalina_home引发的问题
    关于用osgModeling批量生成管道
    Cocos2d-X学习之Ref类
    ApiDemos示例学习(2)——App->Activity->Animation
    ApiDemos示例学习(1)——ApiDemos示例的导入
    eclipse中调出android sdk manager和android virtual device manager图标
    Mono For Android中AlarmManager的使用
  • 原文地址:https://www.cnblogs.com/baocong/p/7525618.html
Copyright © 2011-2022 走看看