zoukankan      html  css  js  c++  java
  • str2int HDU

    题意:

    给出 n 个串,求出这 n 个串所有子串代表的数字的和。

    题解;

    首先可以把这些串构建后缀自动机(sam.last=1就好了),

    因为后缀自动机上从 root走到的任意节点都是一个子串,所有可以利用这个性质来做

    我们发现对于dp[u]−>dp[v]过程,如果之前走到 dp[u] 的有 12,2 两步,假设现在往 3 这条边走,

    得到 1210+3,210+3,那么其实这些值的贡献是可以一次性计算的,无论之前走到 dp[u] 的有几条路,都需要让他们全部 10,而 3 的贡献则是由走到 dp[u] 的路径数确定的。

    那么我们就可以得到第二个方程:

    1. dp1[i] 表示节点 的贡献
    2. dp2[i] 表示之前有多少种方案走到 i
    3. dp1[v]=dp1[v]+dp1[u]10+dp2[u]j
    4. dp2[v]=dp[2[v]+dp2[v]
      1 #include <set>
      2 #include <map>
      3 #include <stack>
      4 #include <queue>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <cstdio>
      8 #include <string>
      9 #include <vector>
     10 #include <cstring>
     11 #include <iostream>
     12 #include <algorithm>
     13 #include <unordered_map>
     14 
     15 #define  pi    acos(-1.0)
     16 #define  eps   1e-9
     17 #define  fi    first
     18 #define  se    second
     19 #define  rtl   rt<<1
     20 #define  rtr   rt<<1|1
     21 #define  bug                printf("******
    ")
     22 #define  mem(a, b)          memset(a,b,sizeof(a))
     23 #define  name2str(x)        #x
     24 #define  fuck(x)            cout<<#x" = "<<x<<endl
     25 #define  sfi(a)             scanf("%d", &a)
     26 #define  sffi(a, b)         scanf("%d %d", &a, &b)
     27 #define  sfffi(a, b, c)     scanf("%d %d %d", &a, &b, &c)
     28 #define  sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
     29 #define  sfL(a)             scanf("%lld", &a)
     30 #define  sffL(a, b)         scanf("%lld %lld", &a, &b)
     31 #define  sfffL(a, b, c)     scanf("%lld %lld %lld", &a, &b, &c)
     32 #define  sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d)
     33 #define  sfs(a)             scanf("%s", a)
     34 #define  sffs(a, b)         scanf("%s %s", a, b)
     35 #define  sfffs(a, b, c)     scanf("%s %s %s", a, b, c)
     36 #define  sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d)
     37 #define  FIN                freopen("../in.txt","r",stdin)
     38 #define  gcd(a, b)          __gcd(a,b)
     39 #define  lowbit(x)          x&-x
     40 #define  IO                 iOS::sync_with_stdio(false)
     41 
     42 
     43 using namespace std;
     44 typedef long long LL;
     45 typedef unsigned long long ULL;
     46 const ULL seed = 13331;
     47 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
     48 const int maxm = 8e6 + 10;
     49 const int INF = 0x3f3f3f3f;
     50 const int mod = 2012;
     51 const int maxn = 1e6 + 7;
     52 
     53 struct Suffix_Automaton {
     54     int last, tot, nxt[maxn << 1][26], fail[maxn << 1];//last是未加入此字符前最长的前缀(整个串)所属的节点的编号
     55     int len[maxn << 1];// 最长子串的长度 (该节点子串数量 = len[x] - len[fa[x]])
     56     int sz[maxn << 1];// 被后缀链接的个数,方便求节点字符串的个数
     57     LL num[maxn << 1];// 该状态子串的数量
     58     LL maxx[maxn << 1];// 长度为x的子串出现次数最多的子串的数目
     59     LL sum[maxn << 1];// 该节点后面所形成的自字符串的总数
     60     LL subnum, sublen;// subnum表示不同字符串数目,sublen表示不同字符串总长度
     61     int X[maxn << 1], Y[maxn << 1]; // Y表示排名为x的节点,X表示该长度前面还有多少个
     62     int minn[maxn << 1], mx[maxn << 1];//minn[i]表示多个串在后缀自动机i节点最长公共子串,mx[i]表示单个串的最长公共子串
     63     void init() {
     64         tot = last = 1;
     65         fail[1] = len[1] = 0;
     66         for (int i = 0; i < 26; i++) nxt[1][i] = 0;
     67     }
     68 
     69     void extend(int c) {
     70         int u = ++tot, v = last;
     71         for (int i = 0; i <= 25; i++) nxt[u][i] = 0;
     72         fail[u] = 0;
     73         len[u] = len[v] + 1;
     74         num[u] = 1;
     75         for (; v && !nxt[v][c]; v = fail[v]) nxt[v][c] = u;
     76         if (!v) fail[u] = 1, sz[1]++;
     77         else if (len[nxt[v][c]] == len[v] + 1) fail[u] = nxt[v][c], sz[nxt[v][c]]++;
     78         else {
     79             int now = ++tot, cur = nxt[v][c];
     80             len[now] = len[v] + 1;
     81             memcpy(nxt[now], nxt[cur], sizeof(nxt[cur]));
     82             fail[now] = fail[cur];
     83             fail[cur] = fail[u] = now;
     84             for (; v && nxt[v][c] == cur; v = fail[v]) nxt[v][c] = now;
     85         }
     86         last = u;
     87         //return len[last] - len[fail[last]];//多添加一个子串所产生不同子串的个数
     88     }
     89 
     90     void get_num() {// 每个节点子串出现的次数
     91         for (int i = 1; i <= tot; i++) X[i] = 0;
     92         for (int i = 1; i <= tot; i++) X[len[i]]++;
     93         for (int i = 1; i <= tot; i++) X[i] += X[i - 1];
     94         for (int i = 1; i <= tot; i++) Y[X[len[i]]--] = i;
     95         for (int i = tot; i >= 1; i--) num[fail[Y[i]]] += num[Y[i]];
     96     }
     97 
     98     void get_maxx(int n) {// 长度为x的子串出现次数最多的子串的数目
     99         get_num();
    100         for (int i = 1; i <= tot; i++) maxx[len[i]] = max(maxx[len[i]], num[i]);
    101     }
    102 
    103     void get_sum() {// 该节点后面所形成的自字符串的总数
    104         get_num();
    105         for (int i = tot; i >= 1; i--) {
    106             sum[Y[i]] = 1;
    107             for (int j = 0; j <= 25; j++)
    108                 sum[Y[i]] += sum[nxt[Y[i]][j]];
    109         }
    110     }
    111 
    112     void get_subnum() {//本质不同的子串的个数
    113         subnum = 0;
    114         for (int i = 1; i <= tot; i++) subnum += len[i] - len[fail[i]];
    115     }
    116 
    117     void get_sublen() {//本质不同的子串的总长度
    118         sublen = 0;
    119         for (int i = 1; i <= tot; i++) sublen += 1LL * (len[i] + len[fail[i]] + 1) * (len[i] - len[fail[i]]) / 2;
    120     }
    121 
    122     void get_sa() { // Y表示排名为x的节点,X表示该长度前面还有多少个
    123         for (int i = 0; i <= tot; i++) X[i] = 0;
    124         for (int i = 1; i <= tot; i++) X[len[i]]++;
    125         for (int i = 1; i <= tot; i++) X[i] += X[i - 1];
    126         for (int i = 1; i <= tot; i++) Y[X[len[i]]--] = i;
    127     }
    128 
    129     void match(char s[]) {//多个串的最长公共子串
    130         mem(mx, 0);
    131         int n = strlen(s), p = 1, maxlen = 0;
    132         for (int i = 0; i < n; i++) {
    133             int c = s[i] - 'a';
    134             if (nxt[p][c]) p = nxt[p][c], maxlen++;
    135             else {
    136                 for (; p && !nxt[p][c]; p = fail[p]);
    137                 if (!p) p = 1, maxlen = 0;
    138                 else maxlen = len[p] + 1, p = nxt[p][c];
    139             }
    140             mx[p] = max(mx[p], maxlen);
    141         }
    142         for (int i = tot; i; i--)
    143             mx[fail[i]] = max(mx[fail[i]], min(len[fail[i]], mx[i]));
    144         for (int i = tot; i; i--)
    145             if (minn[i] == -1 || minn[i] > maxx[i]) minn[i] = mx[i];
    146     }
    147 
    148     void get_kth(int k) {//求出字典序第K的子串
    149         int pos = 1, cnt;
    150         string s = "";
    151         while (k) {
    152             for (int i = 0; i <= 25; i++) {
    153                 if (nxt[pos][i] && k) {
    154                     cnt = nxt[pos][i];
    155                     if (sum[cnt] < k) k -= sum[cnt];
    156                     else {
    157                         k--;
    158                         pos = cnt;
    159                         s += (char) (i + 'a');
    160                         break;
    161                     }
    162                 }
    163             }
    164         }
    165         cout << s << endl;
    166     }
    167 
    168     int dp1[maxn << 1], dp2[maxn << 1];
    169 
    170     void solve() {
    171         get_sa();
    172         mem(dp1, 0), mem(dp2, 0);
    173         dp2[1] = 1;
    174         int ans = 0;
    175         for (int i = 1; i <= tot; i++) {
    176             int u = Y[i];
    177             ans = (ans + dp1[u]) % mod;
    178             for (int j = (u == 1 ? 1 : 0); j <= 9; j++) {
    179                 if (!nxt[u][j + 1]) continue;
    180                 int idx = nxt[u][j + 1];
    181                 dp1[idx] = (dp1[idx] + dp1[u] * 10 + j * dp2[u]) % mod;
    182                 dp2[idx] = (dp2[idx] + dp2[u]) % mod;
    183             }
    184         }
    185         printf("%d
    ", ans);
    186     }
    187 } sam;
    188 
    189 int T;
    190 char s[maxn];
    191 
    192 int main() {
    193 #ifndef ONLINE_JUDGE
    194     FIN;
    195 #endif
    196     while (~sfi(T)) {
    197         sam.init();
    198         while (T--) {
    199             sam.last = 1;
    200             sfs(s + 1);
    201             int len = strlen(s + 1);
    202             for (int i = 1; i <= len; i++) sam.extend((s[i] - '0' + 1));
    203         }
    204         sam.solve();
    205     }
    206 #ifndef ONLINE_JUDGE
    207     cout << "Totle Time : " << (double) clock() / CLOCKS_PER_SEC << "s" << endl;
    208 #endif
    209     return 0;
    210 }
    View Code
  • 相关阅读:
    [转]C#中抽象类和接口的区别
    [转]OO设计原则总结
    [转]MVC3快速搭建Web应用(三)实例篇
    原生内存(堆外内存)
    使用SAX解析XML实例根据属性查找
    Cannot forward after response has been committed问题解决及分析
    dubbo服务化实施整理
    bean:write 标签不能显示出 换行符的解决方案
    Dubbo原理解析监控
    thread之1:java与线程
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/11571630.html
Copyright © 2011-2022 走看看