poj 3395 -- Shift Cipher ( stl + dp )

这篇博客介绍了如何解决POJ 3395 - Shift Cipher问题。由于字典大小约为10万,使用Trie树可能导致内存限制错误,而采用map存储则能避免这个问题。字符串有26种变化,通过枚举并应用n^2的动态规划策略找到单词数最少的解。注意,答案必须满足相邻单词不是单字符且平均字符数大于2的条件。程序用C++编写,成功通过评测,内存使用9988K,运行时间为1188MS。
摘要由CSDN通过智能技术生成

题本身挺水,就是有点坑人,字典大概10W个,用Trie树存会MLE,用map存就好,字符串有26种变化,枚举一遍,输出单词数最小的,n^2 的dp解决,还有一个坑,The answer will be considered correct if no adjacent words are single character and the average number of characters in the words is greater than 2.  加个特判就行了

大概就是这样

Memory: 9988K Time: 1188MS

Language: C++ Result: Accepted

# include <iostream>
# include <set>
# include <map>
# include <vector>
# include <list>
# include <queue>
# include <stack>
# include <cstring>
# include <string>
# include <cstdlib>
# include <cmath>
# include <algorithm>

using namespace std ;

const int MAX = 1e9 ;

string t ;
int cnt , len ;
string ss [ 100000 ] ;
map < string , int > mmap ;
vector < int > vec ;
int stmin , k , ansk ;

void DP ( ){
        int llist [ 300 ] = { 0 } ;
        int num [ 300 ] = { 0 } ;
        int dp [ 300 ] = { 0 } ;
        memset ( dp , -1 , sizeof ( dp ) ) ;
        dp [ 0 ] = 0 ;
        for ( int i = 1 ; i <= len ; i ++ ) {
                int minn = MAX , pos = -1 ;
                map < string , int > :: iterator tmp ;
                for ( int j = 0 ; j < i ; j ++ ) {
                        if ( j == i - 1 ) {
                                if ( llist [ i - 1 ] == i - 2 )     break ;
                        }
                        if ( dp [ j ] != -1 && dp [ j ] + 1 < minn ) {
                                string s ;
                                for ( int h = j ; h < i ; h ++ )
                                        s += t [ h ] ;
                                map < string , int > :: iterator it = mmap . find ( s ) ;
                                if ( it != mmap . end ( ) ) {
                                        minn = dp [ j ] + 1 ;
                                        pos = j ;
                                        tmp = it ;
                                }
                        }
                }
                if ( minn != MAX ) {
                        dp [ i ] = minn ;
                        num [ i ] = tmp -> second ;
                        llist [ i ] = pos ;
                }
        }
        if ( dp [ len ] != -1 && dp [ len ] < stmin && len > dp [ len ] * 2 ) {
                stmin = dp [ len ] ;
                ansk = k ;
                vec . clear ( ) ;
                for ( int i = len ; i ; i = llist [ i ] ) {
                        vec . push_back ( num [ i ] ) ;
                }
        }
}

int main ( )
{
        cin . sync_with_stdio ( false ) ;
        while ( getline ( cin , t ) , t [ 0 ] ) {
                mmap [ t ] = cnt ;
                ss [ cnt ++ ] = t ;
        }

        while ( getline ( cin , t ) , t [ 0 ] != '0' ) {
                stmin = MAX ;
                len = t . size ( ) ;
                for ( k = 0 ; k < 26 ; k ++ ) {
                        DP ( ) ;
                        for ( int i = 0 ; i < len ; i ++ ) {
                                t [ i ] = ( t [ i ] -'a' + 25 ) % 26 + 'a' ;
                        }
                }
                if ( stmin == MAX )     cout << "NO SOLUTIONS" << endl ;
                else {
                        cout << "k=" << ansk << ':' ;
                        for ( int i = vec . size ( ) - 1 ; i >= 0 ; i -- ) {
                                cout << ' ' << ss [ vec [ i ] ] ;
                        }
                        cout << endl ;
                }
        }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值