列表

详情


JD19. 寻找子串

描述

给出 个字符串 S1S2...Sm 和一个单独的字符串 。请在 中选出尽可能多的子串同时满足:  
1)这些子串在 中互不相交。 
2)这些子串都是 S1S2...Sm 中的某个串。
问最多能选出多少个子串。

数据范围: ,输入的每个字符串长度满足

输入描述

第一行一个数m(1≤m≤10),接下来m行,每行一个串。最后一行输入一个串T。输入中所有单个串的长度不超过100000,串中只会出现小写字母。

输出描述

输出一个数,最多能选出多少串。

示例1

输入:

3
aa
b
ac
bbaac

输出:

3

说明:

可选 b b aa 或 b b ac

原站题解

C++ 解法, 执行用时: 20ms, 内存消耗: 13432KB, 提交时间: 2020-12-22

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
  
  
using namespace std;
  
const int N = 110000;
const int M = 10;
  
struct Mp
{
    int len, id;
}mp[M];
bool cmp(Mp a, Mp b)
{
    return a.len<b.len;
}
  
char sn[M][N];
char ss[N];
  
int nextt[M][N];
int match[M][N];
  
void kmp(int n)
{
    int i, j, k;
    int sslen = strlen(ss + 1);
    for (i = 0; i<n; i++)
    {
        nextt[i][1] = 0;
        for (j = 2; j <= mp[i].len; j++)
        {
            int t = nextt[i][j - 1];
            while (t&&sn[i][t + 1] != sn[i][j]) t = nextt[i][t];
            if (sn[i][t + 1] == sn[i][j]) nextt[i][j] = t + 1;
            else nextt[i][j] = 0;
        }
        match[i][0] = 0;
        for (j = 1; j <= sslen; j++)
        {
            int t = match[i][j - 1];
            while (t&&sn[i][t + 1] != ss[j]) t = nextt[i][t];
            if (sn[i][t + 1] == ss[j]) match[i][j] = t + 1;
            else match[i][j] = 0;
            //cout<<match[i][j];
        }
        //cout<<endl;
    }
}
  
int dp[N];
int dfs(int l, int n)
{
    if (l == 0) return 0;
    if (dp[l] != -1) return dp[l];
    int i, j, k;
    int ret = 0;
    for (i = 0; i<n; i++)
    {
        int len = mp[i].len;
        if (match[i][l] == len)
        {
            ret = max(ret, dfs(l - len, n) + 1);
        }
    }
    ret = max(ret, dfs(l - 1, n));
    dp[l] = ret;
    return ret;
}
  
  
  
int main()
{
    int i, j, k, n;
    cin >> n;
    for (i = 0; i<n; i++)
    {
        scanf("%s", sn[i] + 1);
        mp[i].len = strlen(sn[i] + 1), mp[i].id = i;
    }
    scanf("%s", ss + 1);
    kmp(n);
    //sort(mp,mp+n);
    int sslen = strlen(ss + 1);
    memset(dp, -1, sizeof(dp));
    dfs(sslen, n);
    cout << dp[sslen] << endl;
    return 0;
}

C++ 解法, 执行用时: 21ms, 内存消耗: 1804KB, 提交时间: 2020-09-17

/*
author Owen_Q
*/
 
#include<bits/stdc++.h>
 
using namespace std;
 
const int maxn = 1e2+7;
 
string s[maxn];
int a[maxn];
 
int main()
{
    int m;
    cin >> m;
    for(int i=0;i<m;i++)
    {
        cin >> s[i];
        a[i] = s[i].size();
    }
    string t;
    cin >> t;
    int n = t.size();
    int now = 0;
    int pos = 0;
    int re = 0;
    while(now<n)
    {
        for(int i=0;i<m;i++)
        {
            if(pos+a[i]-1<=now)
            {
                int tmp = 0;
                while(tmp<a[i])
                {
                    //cout << s[a[i]-1-tmp] <<"*" << t[now-tmp] << endl;
                    if(s[i][a[i]-1-tmp]!=t[now-tmp])
                        break;
                    tmp++;
                }
                if(tmp == a[i])
                {
                    re++;
                    //cout << now << "*" << i << endl;
                    pos = now+1;
                    break;
                }
            }
        }
       now++;
    }
    cout << re << endl;
    return 0;
}
/*
注意每次改局部代码对整体代码的影响
*/

上一题