POJ 3007-Organize Your Train part II(hash-字符串)

Organize Your Train part II
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8523 Accepted: 2435

Description

RJ Freight, a Japanese railroad company for freight operations has recently constructed exchange lines at Hazawa, Yokohama. The layout of the lines is shown in Figure 1.


Figure 1: Layout of the exchange lines

A freight train consists of 2 to 72 freight cars. There are 26 types of freight cars, which are denoted by 26 lowercase letters from "a" to "z". The cars of the same type are indistinguishable from each other, and each car's direction doesn't matter either. Thus, a string of lowercase letters of length 2 to 72 is sufficient to completely express the configuration of a train.

Upon arrival at the exchange lines, a train is divided into two sub-trains at an arbitrary position (prior to entering the storage lines). Each of the sub-trains may have its direction reversed (using the reversal line). Finally, the two sub-trains are connected in either order to form the final configuration. Note that the reversal operation is optional for each of the sub-trains.

For example, if the arrival configuration is "abcd", the train is split into two sub-trains of either 3:1, 2:2 or 1:3 cars. For each of the splitting, possible final configurations are as follows ("+" indicates final concatenation position):

  [3:1]
    abc+d  cba+d  d+abc  d+cba
  [2:2]
    ab+cd  ab+dc  ba+cd  ba+dc  cd+ab  cd+ba  dc+ab  dc+ba
  [1:3]
    a+bcd  a+dcb  bcd+a  dcb+a

Excluding duplicates, 12 distinct configurations are possible.

Given an arrival configuration, answer the number of distinct configurations which can be constructed using the exchange lines described above.

Input

The entire input looks like the following.

the number of datasets = m
1st dataset 
2nd dataset
 
... 
m-th dataset

Each dataset represents an arriving train, and is a string of 2 to 72 lowercase letters in an input line.

Output

For each dataset, output the number of possible train configurations in a line. No other characters should appear in the output.

Sample Input

4
aa
abba
abcd
abcde

Sample Output

1
6
12
18

Source


题目意思

一串字符,被分成两个部分,从上面走的字符串被反转,从下面走的字符串先输出来,计算所有不同组合方式的数目。

解题思路

嗯哼(,,• ₃ •,,)我只会暴力枚举,然后map妥妥的TLE…改了hash才水过去…
第一部分串的长度范围是1~len-1,根据长度枚举两个串的四种情况:
①都走上面:反转S1和S2;
②都走下面:都不变;
③第一个走上面第二个走下面:反转S1,S2不变;
④第一个走下面第二个走上面:反转S2,S1不变。
对于这四种情况,每一个又可以分成两种情况:①上面的串先出②下面的串先出。
所以一共是八种情况。
用hash对每次组合出的串判断,统计不同的个数即可。

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define INF 0xfffffff
const int MAXN=99991;
const int MAXM=100;
char c[MAXM];//原始串
char s1[MAXM],s1[MAXM];//分割的两个串
char t1[MAXM],t2[MAXM];//保留原始分割的两个串
char s[MAXM];//最终连结的串
//map<std::string,bool> ma;
void reserve(char x[])//反转字符串
{
    char temp[MAXN];
    int n=strlen(x),cnt=0;
    for(int i=n-1; i>=0; --i)
        temp[cnt++]=x[i];
    temp[cnt]='\0';
    strcpy(x,temp);
}
typedef struct node
{
    char str[MAXM];
    node *next;
    node()
    {
        next=0;
    }
} Point;

Point *Head[MAXN];

bool Hash(char *s) //哈希处理冲突
{
    int len=strlen(s);
    int num=0;
    for(int i=0; i<len; i++)
    {
        num=num+s[i]*(i+1);
        num%=MAXN;
    }
    if(Head[num]==NULL)
    {
        Point*p=new Point;
        strcpy(p->str,s);
        Head[num]=p;
        return true;
    }
    else
    {
        Point *p = Head[num];
        while(p)
        {
            if(strcmp(p->str,s)==0) return false;
            p=p->next;
        }
        p=new Point;
        strcpy(p->str,s);
        p->next = Head[num];
        Head[num] = p;
    }
    return true;
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("G:/cbx/read.txt","r",stdin);
    //freopen("G:/cbx/out.txt","w",stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",&c);
        int len=strlen(c);
        int ans=0;
        for(int k=1; k<len; ++k)//分割点
        {
            memset(s1,'\0',sizeof(s1));
            int cnt1=0;//第一串长度
            for(int i=0; i<k; ++i)//第一串
                s1[cnt1++]=c[i];
            cnt1=strlen(s1);
            memset(s2,'\0',sizeof(s2));
            int cnt2=0;//第二串长度
            for(int i=k; i<len; ++i)//第二串
                s2[cnt2++]=c[i];
            memcpy(t1,s1,cnt1);
            memcpy(t2,s2,cnt2);
            //上上
            reserve(s1);
            reserve(s2);
            int cnt=0;
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录

            cnt=0;
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录
            //下下
            memcpy(s1,t1,cnt1);
            memcpy(s2,t2,cnt2);
            cnt=0;
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录

            cnt=0;
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录
            //上下
            memcpy(s1,t1,cnt1);
            memcpy(s2,t2,cnt2);
            reserve(s1);
            cnt=0;
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录

            cnt=0;
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录
            //下上
            memcpy(s1,t1,cnt1);
            memcpy(s2,t2,cnt2);
            reserve(s2);
            cnt=0;
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录

            cnt=0;
            for(int i=0; i<cnt2; ++i)
                s[cnt++]=s2[i];
            for(int i=0; i<cnt1; ++i)
                s[cnt++]=s1[i];
            //cout<<s<<" "<<s1<<" "<<s2<<endl;
            if(Hash(s)) ++ans;//记录
        }
        printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值