题目链接:
题目大意:
给出一个字符串,问能否拆出三个不重叠的字串然后连接在一起凑成anniversary。
题目分析:
给出的串我们设为s,模式匹配串我们设为p,设dp[i][j]为当前串以第i个字符结尾模式串以j个字符结尾能够匹配的最大的长度。
那么如果s[i] == p[j] , 那么dp[i][j] = dp[i-1][j-1] + 1
否则dp[i][j] = 0;
那么之后我们直接暴力求解即可。
就是找到每次切割的字符串的点,然后利用dp[i][j]判断当前切割方法能否保证能够完全覆盖p串,然后判断是否是切割出了三个串,如果是的话那么就是能够切割,否则就是不能。枚举所有情况
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
int t,n,m;
char p[]="anniversary";
char s[107];
int dp[107][107];
bool flag;
void dfs ( int i , int j , int cnt )
{
//cout << i <<" " << j << " " << cnt<< endl;
if ( flag ) return;
if ( j == m-1 )
{
if ( cnt != 3 ) return;
flag = true;
return;
}
for ( int k = i+1 ; k < n ; k++ )
for ( int l = j+1 ; l < m ; l++ )
{
if ( j+dp[k][l] >= l && i+(l-j) <= k )
{
dfs ( k , l , cnt+1);
}
}
}
int main ( )
{
scanf ( "%d" , &t );
while ( t-- )
{
scanf ( "%s" , s );
n = strlen ( s );
m = strlen ( p );
memset ( dp , 0 , sizeof ( dp ));
for ( int i = 0 ; i < n ; i++ )
for ( int j = 0 ; j < m ; j++ )
if ( s[i] == p[j] )
{
if ( i == 0 || j == 0 )
dp[i][j] = 1;
else
dp[i][j] = dp[i-1][j-1] + 1;
}
flag = false;
dfs ( -1 , -1 , 0 );
if ( flag ) puts ( "YES" );
else puts ( "NO" );
}
}