1 条题解

  • 1
    @ 2025-4-3 21:16:58

    题意

    给出nn个字符串,求他们相连的最小长度,如果首尾字母相同则可以共用相同部分,比如两个串ABCDEFABCDEFDEFGHIDEFGHI,他们相连为ABCDEFGHIABCDEFGHI,最小长度为99,中间的DEFDEF部分共用了。

    思路

    由于数据量较小,首先对每两个字符串aba,b用扩展KMPKMP求出aa连在bb之后可以共用的长度,用数组B[i][j]B[i][j]表示第jj个字符串连接在第ii个字符串后面能共用的最大长度。 1.在扩展KMPKMP函数中求子串aa和母串bb的公共前缀数组ret[i]ret[i](子串、母串、公共前缀数组,为了理解方便,我就这么叫了),如果此时ret[i]ret[i]strlen(b)istrlen(b)-i的值相等,说明bb串剩下的部分和aa串的前strlen(b)istrlen(b)-i个字符完全相等,则这个值就是我们需要的值,因为ii是从小到大的,所以如果找到符合的strlen(b)istrlen(b)-i值,最先出现的这个值一定是最大的,即可返回,如果最后没有找到符合的值,说明没有bb串的后缀和aa串的前缀相等,则返回00。 2.找完了数组BB中所有值之后,考虑到一个字符串最多只能连在一个字符串的后面,并且身后也最多只能连接一个字符串,而且此题数据较小,可以用dfsdfs来枚举,枚举每个串当首串的情况(即它不连在其他串之后),然后dfsdfs枚举每个串连在它身后的情况,找出这之中的最小值,就是我们需要的答案。

    标程

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    #define PI acos(-1.0)
    #define MAXN 10100
    #define eps 1e-7
    #define INF 0x7FFFFFFF
    #define LLINF 0x7FFFFFFFFFFFFFFF
    #define seed 131
    #define MOD 1000000007
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    char a[15][25];
    int next[MAXN], ret[MAXN];
    int b[15][15], vis[15];
    int ans, n;
    
    int ExtendKMP(char a[], char b[]) {
        int i, j, k;
        int M = strlen(a);
        int N = strlen(b);
        
        for (j = 0; 1 + j < M && a[j] == a[1 + j]; j++);
        next[1] = j;
        k = 1;
        for (i = 2; i < M; i++) {
            int Len = k + next[k], L = next[i - k];
            if (L < Len - i) {
                next[i] = L;
            } else {
                for (j = (Len - i > 0) ? (Len - i) : 0; i + j < M && a[j] == a[i + j]; j++);
                next[i] = j;
                k = i;
            }
        }
        
        for (j = 0; j < N && j < M && a[j] == b[j]; j++);
        if (j == N) return N;
        ret[0] = j;
        k = 0;
        for (i = 1; i < N; i++) {
            int Len = k + ret[k], L = next[i - k];
            if (L < Len - i) {
                ret[i] = L;
            } else {
                for (j = (Len - i > 0) ? (Len - i) : 0; j < M && i + j < N && a[j] == b[i + j]; j++);
                ret[i] = j;
                k = i;
            }
            if (ret[i] == N - i) return ret[i];
        }
        return 0;
    }
    
    void dfs(int x, int tot, int len) {
        int i;
        if (tot == n) {
            if (ans > len) ans = len;
            return;
        }
        if (len > ans) return;
        for (i = 0; i < n; i++) {
            if (!vis[i]) {
                vis[i] = 1;
                dfs(i, tot + 1, len + strlen(a[i]) - b[i][x]);
                vis[i] = 0;
            }
        }
    }
    
    int main() {
        int t, i, j;
        scanf("%d", &t);
        while (t--) {
            memset(b, 0, sizeof(b));
            memset(vis, 0, sizeof(vis));
            ans = INF;
            scanf("%d", &n);
            for (i = 0; i < n; i++) {
                scanf("%s", a[i]);
            }
            for (i = 0; i < n; i++) {
                for (j = 0; j < n; j++) {
                    if (i == j) continue;
                    b[j][i] = ExtendKMP(a[i], a[j]);
                }
            }
            for (i = 0; i < n; i++) {
                vis[i] = 1;
                dfs(i, 1, strlen(a[i]));
                vis[i] = 0;
            }
            printf("%d\n", ans);
        }
        return 0;
    }
    
    • 1

    信息

    ID
    700
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者