hdu 4436 str2int (SAM)(待補)

參考:http://blog.csdn.net/u013654696/article/details/40661797
In this problem, you are given several strings that contain only digits from ‘0’ to ‘9’, inclusive.
An example is shown below.
101
123
The set S of strings is consists of the N strings given in the input file, and all the possible substrings of each one of them.
It’s boring to manipulate strings, so you decide to convert strings in S into integers.
You can convert a string that contains only digits into a decimal integer, for example, you can convert “101” into 101, “01” into 1, et al.
If an integer occurs multiple times, you only keep one of them.
For example, in the example shown above, all the integers are 1, 10, 101, 2, 3, 12, 23, 123.
Your task is to calculate the remainder of the sum of all the integers you get divided by 2012.
Input
There are no more than 20 test cases.
The test case starts by a line contains an positive integer N.
Next N lines each contains a string consists of one or more digits.
It’s guaranteed that 1≤N≤10000 and the sum of the length of all the strings ≤100000.
The input is terminated by EOF.
Output
An integer between 0 and 2011, inclusive, for each test case.
Sample Input

5
101
123
09
000 
1234567890

Sample Output

202

給n個只包含數字的字符串, 問這n個字符串能分解爲多少種不同的數字, 求出這些數字的和mod2012

先把n個串用10連接起來, 然後構造sam。 然後計數的時候可以從拓撲序從小到大計數,(以前一直以爲只能從大到小。。。), cnt[i]表示這個節點上有多少種數, sum[i]表示這個節點之前的能構成的數的和是多少,轉移就是直接轉移到兒子上就可以了。。。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

#define mnx 200020
#define mod 2012

int ch[mnx << 1][12], par[mnx << 1], val[mnx << 1], sz;
int cnt[mnx << 1], sum[mnx << 1];
int root, lst;

int creat(int v) {
    ++sz;
    val[sz] = v;
    par[sz] = 0;
    cnt[sz] = 0;
    sum[sz] = 0;
    memset(ch[sz], 0, sizeof(ch[sz]));
    return sz;
}

void extend(int c) {
    int p = lst;
    int np = creat(val[p] + 1);
    while(p && ch[p][c] == 0)
        ch[p][c] = np, p = par[p];
    if(!p) par[np] = root;
    else {
        int q = ch[p][c];
        if(val[q] == val[p] + 1)
            par[np] = q;
        else {
            int nq = creat(val[p] + 1);
            memcpy(ch[nq], ch[q], sizeof(ch[q]));
            par[nq] = par[q];
            par[q] = nq;
            par[np] = nq;
            while(p && ch[p][c] == q)
                ch[p][c] = nq, p = par[p];
        }
    }
    lst = np;
}

int b[mnx << 1], d[mnx];

char s[mnx];
int n, len;

int main() {
    while(scanf("%d", &n) != EOF) {
        sz = 0;
        root = lst = creat(0);
        len = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%s", s);
            len += strlen(s);
            for(int j = 0; s[j]; ++j)
                extend(s[j] - '0');
            extend(10);
            ++len;
        }
        memset(d, 0, sizeof(d));
        for(int i = 1; i <= sz; ++i) ++d[val[i]];
        for(int i = 1; i <= len; ++i) d[i] += d[i - 1];
        for(int i = 1; i <= sz; ++i) b[d[val[i]]--] = i;
        memset(cnt, 0, sizeof(cnt));
        memset(sum, 0, sizeof(sum));
        cnt[1] = 1;
        for(int i = 1; i <= sz; ++i) {
            int u = b[i];
            for(int j = 0; j < 10; ++j) {
                if(u == 1 && j == 0) continue; //去除前導0的情況。
                if(ch[u][j] == 0) continue;
                int v = ch[u][j];
                int add = (sum[u] * 10 + j * cnt[u]) % mod;
                sum[v] = (sum[v] + add) % mod;
                cnt[v] += cnt[u];
                cnt[v] %= mod;
            }
        }
        int ans = 0;
        for(int i = 1; i <= sz; ++i) 
            ans = (ans + sum[i]) % mod;
        printf("%d\n", ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章