天天看点

Bupt summer training for 2013_String

A - Crazy Search(POJ 1200)      

解题思路:

还有什么比离散化之后直接hash解决简单粗暴的呢?

#include <algorithm>

#include <iostream>

#include <iomanip>

#include <cstring>

#include <climits>

#include <complex>

#include <fstream>

#include <cassert>

#include <cstdio>

#include <bitset>

#include <vector>

#include <deque>

#include <queue>

#include <stack>

#include <ctime>

#include <set>

#include <map>

#include <cmath>

#define eps 1e-9

#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

typedef unsigned long long ull;

typedef long double ld;

typedef pair<ll, ll> pll;

typedef complex<ld> point;

typedef pair<int, int> pii;

typedef pair<pii, int> piii;

template<class T>

inline bool read(T &n)

{

T x = 0, tmp = 1; char c = getchar();

while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();

if(c == EOF) return false;

if(c == '-') c = getchar(), tmp = -1;

while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();

n = x*tmp;

return true;

}

template <class T>

inline void write(T n)

{

if(n < 0)

{

putchar('-');

n = -n;

}

int len = 0,data[20];

while(n)

{

data[len++] = n%10;

n /= 10;

}

if(!len) data[len++] = 0;

while(len--) putchar(data[len]+48);

}

//-----------------------------------

const int MAXN=16000010;

const int MOD=100007;

char str[MAXN];

bool hash[10000000];

int ansi[256];

int main()

{

int n,nc;

while(read(n)&&read(nc))

{

int ans=0;

gets(str);

memset(hash,0,sizeof(hash));

memset(ansi,0,sizeof(ansi));

int len=strlen(str);

for(int i=0;i<len;i++)

ansi[str[i]]=1;

int cnt=0;

for(int i=0;i<256;i++)

if(ansi[i])

ansi[i]=cnt++;

for(int i=0;i<len-n+1;i++)

{

ull sum=0;

for(int j=i;j<i+n;j++)

sum=sum*nc+ansi[str[j]];

if(!hash[sum])

{

ans++;

hash[sum]=true;

}

}

write(ans);

putchar('\n');

}

return 0;

}

B - Power Strings

利用KMP的失配函数,将自己作为模板链进行匹配

然后根据失配数组的性质计算出向前移动几位数字使得字符串匹配

则移动的数字就是循环节

#include <algorithm>

#include <iostream>

include <cstring>

#include <iomanip>

##include <climits>

#include <complex>

include <cstdio>

#

#include <fstream>

#include <cassert>

#include <bitset>

#include <vector>

#include <deque>

nclude <set>

#in

#include <queue>

#include <stack>

#include <ctime>

#

iclude <map>

#include <cmath>

#define EPS 1e-10

namespace std;

temp

#define INF 0x3f3f3f3f

#define ll __int64

usin

glate<class T>

inline bool read(T &n)

{

;

while((c < '0' || c > '9') && c !=

T x = 0, tmp = 1; char c = getchar(

)'-' && c != EOF) c = getchar();

if(c == EOF) return false;

c <= '9') x *= 10, x += (c - '0'),c = get

if(c == '-') c = getchar(), tmp = -1;

while(c >= '0' &&

char();

n = x*tmp;

return true;

}

-----------------------------const int MAXN=10000010; char str[MAXN]; -----------------------------

const int MAXN=10000010;

char str[MAXN];

//-----------------------------------------

-

int next[MAXN];

int getFail()

{

next[0]=next[1]=0;

int n=strlen(str);

for(int i=1;i<n;i++)

{

xt[n]>0&&n%(n-next

int j=next[i];

while(j&&str[i]!=str[j])

j=next[j];

next[i+1]=str[i]==str[j]?j+1:0;

}

if(n

e[n])==0)

return n/(n-next[n]);

else

return 1;

}

int main()

{

while(scanf("%s",str)!=EOF)

{

if(str[0] == '.')

continue;

printf("%d\n",getFail());

}

return 0;

}

C - Colored Sticks

Trie树+并查集+欧拉回路

将所有出现过的字符串插入Trie树,并返回编号

将所有颜色的编号用并查集维护起来,并且记录编号的入度

最后查看有多少点不在并查集中,以及欧拉回路的入度奇偶性

#include <algorithm>

#include <iostream>

#include <iomanip>

#include <cstring>

#include <climits>

#include <complex>

#include <fstream>

#include <cassert>

#include <cstdio>

#include <bitset>

#include <vector>

#include <deque>

#include <queue>

#include <stack>

#include <ctime>

#include <set>

#include <map>

#include <cmath>

#define CLR(x,y) memset(x,y,sizeof(x))

#define eps 1e-9

#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

typedef long double ld;

typedef pair<ll, ll> pll;

typedef complex<ld> point;

typedef pair<int, int> pii;

typedef pair<pii, int> piii;

template<class T>

inline bool read(T &n)

{

T x = 0, tmp = 1; char c = getchar();

while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();

if(c == EOF) return false;

if(c == '-') c = getchar(), tmp = -1;

while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();

n = x*tmp;

return true;

}

template <class T>

inline void write(T n)

{

if(n < 0)

{

putchar('-');

n = -n;

}

int len = 0,data[20];

while(n)

{

data[len++] = n%10;

n /= 10;

}

if(!len) data[len++] = 0;

while(len--) putchar(data[len]+48);

}

//-----------------------------------

const int MAXN=500005;

struct Trie

{

int child[MAXN*10][26],root;

int flag[MAXN*10];

int sz;

int idx(char c) { return c-'a'; }

Trie()

{

root=sz=1;CLR(child[1],0);flag[1]=0;

}

void insert(const char *str,const int v)

{

int *cur=&root;

for(const char *p=str;*p;p++)

{

cur=&child[*cur][idx(*p)];

if(*cur==0)

{

*cur=++sz;

CLR(child[sz],0);

flag[*cur]=0;

}

}

flag[*cur]=v;

}

int find(const char *str)

{

int *cur=&root;

for(const char *p=str;*p && *cur;p++)

cur=&child[*cur][idx(*p)];

if(*cur==0)

return 0;

return flag[*cur];

}

}trie;

int fa[MAXN];

int find_fa(int x)

{

if(fa[x]==x)

return x;

else

return fa[x]=find_fa(fa[x]);

}

void Merge(int x,int y)

{

int xx=find_fa(x),yy=find_fa(y);

fa[xx]=yy;

}

char a[20],b[20];

int deg[MAXN];

void init()

{

for(int i=1;i<MAXN;i++)

fa[i]=i,deg[i]=0;

}

bool check(int cnt)

{

int euler=0;

int father=0,fath=find_fa(1);

for(int i=1;i<cnt;i++)

{

euler+=(deg[i]&1);

father+=( find_fa(i)!=fath );

}

return father || euler>2;

}

int main()

{

// freopen("data.txt","r",stdin);

int cnt=1;

init();

while(scanf("%s %s",a,b)!=EOF)

{

int s=trie.find(a);

if(!s)

{

trie.insert(a,cnt);

s=cnt++;

}

int t=trie.find(b);

if(!t)

{

trie.insert(b,cnt);

t=cnt++;

}

if(find_fa(s)!=find_fa(t))

Merge(s,t);

deg[s]++;

deg[t]++;

}

if(check(cnt))

puts("Impossible");

else

puts("Possible");

return 0;

}

D - DNA repair

解题思路以及见:http://blog.csdn.net/u013007900/article/details/38490739

E - Kindergarten

这题和字符串没啥关系吧?

本题是要求图中的最大完全子图(最大团)中顶点的个数(最大团的规模 或 称为 最大完全数)。普通图的最大团则是一个NP问题,目测是要暴力枚举。

由于原图的补图是一个二分图,其 最大完全数 等价于其补图的最大独立集中元素的个数,于是可以根据二分图的性质求出这个最大独立集。

定理:

二分图最大独立集=顶点数 - 二分图最大匹配

最大完全数 = 原图补图的 最大独立集的规模

概念:

最大完全子图:每个点都两两相连,共有 n * ( n-1 )  / 2 条边,又称为最大团

最大完全数:图中最大完全子图的顶点个数,又称为最大团的规模

独立集:图中任意两个顶点都不相连的顶点集合,可以理解为孤立点的集合

补图:原来图连边的不连,不连边的连边,形成的新图称为补图

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>
#define CLR(x,y) memset(x,y,sizeof(x))
#define eps 1e-9
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef complex<ld> point;
typedef pair<int, int> pii;
typedef pair<pii, int> piii;

template<class T>
inline bool read(T &n)
{
    T x = 0, tmp = 1; char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == EOF) return false;
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
    return true;
}
template <class T>
inline void write(T n)
{
    if(n < 0)
    {
        putchar('-');
        n = -n;
    }
    int len = 0,data[20];
    while(n)
    {
        data[len++] = n%10;
        n /= 10;
    }
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
//-----------------------------------

const int MAXN=210;

bool mapp[MAXN][MAXN];
int from[MAXN],G,B,m;
bool used[MAXN];

bool match(int x)
{
	for(int i=1;i<=B;i++)
		if(mapp[x][i] && !used[i])
		{
			used[i]=true;
			if(from[i]==-1 || match(from[i]))
			{
				from[i]=x;
				return true;
			}
		}
	return false;
}

int hungry()
{
	int tot=0;
	CLR(from,-1);
	for(int i=1;i<=G;i++)
	{
		CLR(used,0);
		if(match(i))
			tot++;
	}
	return tot;
}


int main()
{
    freopen("data.txt","r",stdin);
    int Cas=1;
	while(read(G)&&read(B)&&read(m)&&G&&B&&m)
	{
	    for(int i=1;i<=G;i++)
            for(int j=1;j<=B;j++)
                mapp[i][j]=true;
		int u,v;
		for(int i=0;i<m;i++)
		{
			read(u),read(v);
			mapp[u][v]=false;
		}
		printf("Case %d: %d\n",Cas++,B+G-hungry());
	}
	return 0;
}
           

Trie树+并查集+欧拉回路

将所有出现过的字符串插入Trie树,并返回编号

将所有颜色的编号用并查集维护起来,并且记录编号的入度

最后查看有多少点不在并查集中,以及欧拉回路的入度奇偶性