hdu 5311 Hidden String(dp+暴力dfs)

题目链接:

点击打开链接

题目大意:

给出一个字符串,问能否拆出三个不重叠的字串然后连接在一起凑成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" );
    }
}


你可能感兴趣的:(C++,动态规划,DFS)