FZU-2218-Simple String Problem【状态压缩dp】

2218-Simple String Problem

Problem Description
Recently, you have found your interest in string theory. Here is an interesting question about strings.

You are given a string S of length n consisting of the first k lowercase letters.

You are required to find two non-empty substrings (note that substrings must be consecutive) of S, such that the two substrings don’t share any same letter. Here comes the question, what is the maximum product of the two substring lengths?

Input
The first line contains an integer T, meaning the number of the cases. 1 <= T <= 50.

For each test case, the first line consists of two integers n and k. (1 <= n <= 2000, 1 <= k <= 16).

The second line is a string of length n, consisting only the first k lowercase letters in the alphabet. For example, when k = 3, it consists of a, b, and c.

Output
For each test case, output the answer of the question.

Sample Input
4
25 5
abcdeabcdeabcdeabcdeabcde
25 5
aaaaabbbbbcccccdddddeeeee
25 5
adcbadcbedbadedcbacbcadbc
3 2
aaa

Sample Output
6
150
21
0

题目链接:FZU-2218

题目大意:给出一个len长度字符串,只包含n个字母。求两个字串,相互间不包含相同字母的长度的乘积最大

题目思路:状态压缩dp

    * n^2的复杂度,求出每个状态( 1<<n )所能达到的最大长度。
    * dp,求出字母种类小于等于当前state所能达到的最大值(因为可能包含abc和efg的乘积没有ab和efg的乘积大) 
    * 枚举求此类abc和不含abc的字母dp的乘积得最大值

以下是代码:

//
// FZU-2218.cpp
// ZOJ
//
// Created by pro on 16/4/15.
// Copyright (c) 2016年 pro. All rights reserved.
//

#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
int dp[70000];
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        int len,n;
        cin >> len >> n;
        string s;
        cin >> s;
        for (int i = 0; i < len; i++)
        {
            int state = 0;
            for (int j = i; j < len; j++)
            {
                state = state | (1 << (s[j] - 'a'));
                dp[state] = max(dp[state],j - i + 1);    //state状态下(即只包含这个字串的几个字母)所能达到的最大长度
            }
        }

        for (int i = 0; i < (1 << n); i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (i & (1 << j))
                {
                    int state1 = i - (1 << j);   //10110 -> 如果是第1位, state1 = 00110
                    dp[i] = max(dp[i],dp[state1]);
                }

            }

        }
        int ans = 0;
        for (int i = 0; i < (1 << n); i++)
        {
           ans = max(ans,dp[i] * dp[((1 << n) - 1) ^ i]);
        }
        cout << ans << endl;
    }
    return 0;
}

你可能感兴趣的:(压缩,String,dp)