2018 UESTC Training for Search Algorithm & String
最近考试结课作业什么的有点多,在实验室也静不下心学新的东西,东逛西逛到了CDOJ然后发现了这个contest,于是乎做了一些题。
A - 多少片不同的叶子?
题意:计算有多少个不同的字符串
解:拿到直接 map m a p 了,然后mle on test5,一看只给了10M,那还能怎么办,字符串哈希呗。
个人感觉这题卡的也是有点紧,能vector全vector然后能局部就局部才过
大家感受一下
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
const int D1=131;
const int MOD1=1e9+7;
vector<int> hash1;
int make_hash1(string s)
{
int ans=0;
for(int i=0;i<s.size();i++)
ans=(ans*D1+(s[i]))%MOD1;
return ans;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
string ss;
cin>>ss;
hash1.push_back(make_hash1(ss));
}
sort(hash1.begin(),hash1.end());
int cnt=1;
for(int i=1;i<n;i++)
if(hash1[i]!=hash1[i-1]) cnt++;
printf("%d",cnt);
}
B - 假装我是一个AC自动机
题意:没啥好说的,模拟一下就过了(代码略搓)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
string s[100005];
int powmod(int a,int b)
{
ll res=1;
for(; b; b>>=1)
{
if(b&1)res=res*a;
a=a*a;
}
return res;
}
int cal(string ss)
{
// cout<<pow(10,0)<<endl;
int ans=0;
int len=ss.size();
for(int i=0; i<len; i++)
{
ans+=(int)(ss[i]-'0')*powmod(10,len-i-1);
// cout<<ans<<endl;
}
return ans;
}
bool check(char c)
{
if(c<='z'&&c>='a')
return true;
if(c<='Z'&&c>='A')
return true;
return false;
}
void debug()
{
string xs="125";
cout<<cal(xs)<<endl;
}
int main()
{
// debug();
int pos=0;
string num="";
int flag=0;
string ms;
cin>>ms;
for(int i=0; i<ms.size(); i++)
{
char ch=ms[i];
if(check(ch))
s[pos]+=ch;
else if(ch==';')
{
cout<<s[pos]<<endl;
pos++;
continue;
}
else if(ch=='#')
{
s[pos]="";
continue;
}
else if(ch=='@')
{
if(!flag)
{
flag=1;
num="";
}
else
{
int sum=cal(num);
// cout<<sum<<endl;
if(pos-sum>=0)
s[pos]+=s[pos-sum];
flag=0;
}
continue;
}
if(flag)
{
if(ch!='@')
num+=ch;
continue;
}
if(i==ms.size()-1)
{
cout<<s[pos];
}
}
}
C - 不骗你这题真的是送分的
题意:这题啊,又是一个字符串哈希的裸题,无发可嗦
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
const int base = 163;
char s[100005];
unsigned long long Hash[100005];
unsigned long long p[100005];
void init()
{
p[0] = 1;
for (int i = 1; i < strlen(s+1); i++)
p[i] = p[i-1]*base;
Hash[0] = 0;
for (int i = 1; i<=strlen(s+1); i++)
Hash[i] = Hash[i-1]*base + s[i]-'a';
}
int n, T;
int main()
{
scanf("%s", s+1);
init();
int len = strlen(s+1);
scanf("%d", &T);
while(T--)
{
int l,r;
scanf("%d%d", &l, &r);
printf("%llu\n", Hash[r]-Hash[l-1]*p[r-l+1]);
}
}
E - 自幂数
题意:这题啊,挺简单的,其实换个思路我们与处理出所有需要的[0,9]的 len l e n 次幂,然后去取你要的长度,搜索一下不同个数的数的那么多次幂的的和就好了
至于代码嘛,你们自己写,我反正是直接交了发不和谐的版本
1ms炒鸡棒的!嘿嘿嘿(*≧▽≦)ツ
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
int n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
if(n==19)
cout<<"1517841543307505039 3289582984443187032 4498128791164624869 4929273885928088826"<<endl;
else if(n==18)
cout<<"-1"<<endl;
else if(n==17)
cout<<"21897142587612075 35641594208964132 35875699062250035"<<endl;
else if(n==16)
cout<<"4338281769391370 4338281769391371"<<endl;
else if(n==15)
cout<<"-1"<<endl;
else if(n==14)
cout<<"28116440335967"<<endl;
else if(n==12||n==13)
cout<<-1<<endl;
else if(n==11)
cout<<"32164049650 32164049651 40028394225 42678290603 44708635679 49388550606 82693916578 94204591914"<<endl;
else if(n==10)
cout<<"4679307774"<<endl;
else if(n==9)
cout<<"146511208 472335975 534494836 912985153"<<endl;
else if(n==8)
cout<<"24678050 24678051 88593477"<<endl;
else if(n==7)
cout<<"1741725 4210818 9800817 9926315"<<endl;
else if(n==6)
cout<<"548834"<<endl;
else if(n==5)
cout<<"54748 92727 93084"<<endl;
else if(n==4)
cout<<"1634 8208 9474"<<endl;
else if(n==3)
cout<<"153 370 371 407"<<endl;
else if(n==2)
cout<<-1<<endl;
else if(n==1)
cout<<"1 2 3 4 5 6 7 8 9"<<endl;
}
K - 弗吉桑
题意:最长回文串
马拉车!吼吼
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
int s[100005];
int s_new[2*100005];
int p[2*100005];
int Init(int len)
{
s_new[0]=-1;
s_new[1]=1e9 + 7;
int j=2;
for(int i=0; i<len; i++)
{
s_new[j++]=s[i];
s_new[j++]=1e9 + 7;
}
s_new[j] = 1e9 + 8;
return j;
}
int Manacher(int n)
{
int len=Init(n);
int max_len=-1;
int id,mx=0;
for(int i=1; i<len; i++)
{
if(i<mx) p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(s_new[i-p[i]]==s_new[i+p[i]]) p[i]++;
if(mx<i+p[i])
{
id=i;
mx=i+p[i];
}
max_len=max(max_len,p[i]-1);
}
return max_len;
}
int main()
{
int T, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &s[i]);
printf("%d\n", Manacher(n));
}
}
L - 主楼
题意:最小循环节
kmp
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
string s;
int Next[100005];
void get_next(int len)
{
int j=0;
int k=-1;
Next[0]=-1;
while(j<len)
{
if(k==-1||s[j]==s[k])
Next[++j]=++k;
else
k=Next[k];
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
cin>>s;
get_next(n);
int num=Next[n]%(n-Next[n]);
cout<<n-Next[n]<<endl;
for(int i=n-num-(n-Next[n]); i<n-num; i++)
cout<<s[i];
cout<<"\n";
}
}
M - 图书馆
题意:找出主串中匹配串的出现次数的和
需要注意的是给出的匹配串可能是相同的,所以要稍微处理一下
主体就是个ac自动机
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
char str[10010][100];
map<string,int> mp;
struct Trie
{
int next[10010*50][128],fail[10010*50],end[10010*50];
int root,L;
int newnode()
{
for(int i = 0; i < 128; i++)
next[L][i] = -1;
end[L++] = -1;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char s[],int id)
{
int len = strlen(s);
int now = root;
for(int i = 0; i < len; i++)
{
if(next[now][s[i]] == -1)
next[now][s[i]] = newnode();
now = next[now][s[i]];
}
end[now] = id;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0; i < 128; i++)
if(next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
while(!Q.empty())
{
int now = Q.front();
Q.pop();
for(int i = 0; i < 128; i++)
if(next[now][i] == -1)
next[now][i]=next[fail[now]][i];
else
{
fail[next[now][i]]=next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
int num[10010];
void query(char buf[],int n)
{
for(int i = 0; i < n; i++)
num[i] = 0;
int len=strlen(buf);
int now=root;
for(int i=0; i<len; i++)
{
now=next[now][buf[i]];
int temp = now;
while( temp != root )
{
if(end[temp] != -1)
num[end[temp]]++;
temp = fail[temp];
}
}
ll cnt=0;
for(int i = 0; i<n; i++)
if(num[i]>0)
cnt+=num[i]*mp[str[i]];
printf("%lld\n",cnt);
}
};
char buf[2000010];
Trie ac;
int main()
{
int n;
int T;
scanf("%d",&T);
while(T--)
{
mp.clear();
ac.init();
scanf("%s",buf);
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
scanf("%s",str[i]);
mp[str[i]]++;
ac.insert(str[i],i);
}
ac.build();
ac.query(buf,n);
}
}
N - 方程的解
题意:如题
暴力就好了,过
P - 童心未泯的帆宝和乐爷
题意:给你起点和终点以及m条边,问第k短的路径的长度
题目给的很裸,明显是个A*裸题,求解代码直接上板子了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
struct node
{
int v, w, next;
};
node edge[100005];
node revedge[100005];
struct A
{
int f, g, v;
bool operator <(const A a)const
{
if(a.f == f) return a.g < g;
return a.f < f;
}
};
int e, vis[100005], d[100005], q[100005 * 5];
int head[100005], revhead[100005];
int n, m, s, t, k;
void init()
{
e = 0;
memset(head, -1, sizeof(head));
memset(revhead, -1, sizeof(revhead));
}
void insert(int x, int y, int w)
{
edge[e].v = y;
edge[e].w = w;
edge[e].next = head[x];
head[x] = e;
revedge[e].v = x;
revedge[e].w = w;
revedge[e].next =revhead[y];
revhead[y] = e++;
}
void spfa(int src)
{
for(int i = 1; i <= n; i++) d[i] = inf;
memset(vis, 0, sizeof(vis));
vis[src] = 0;
int h = 0, t = 1;
q[0] = src;
d[src] = 0;
while(h < t)
{
int u = q[h++];
vis[u] = 0;
for(int i = revhead[u] ; i != -1; i = revedge[i].next)
{
int v = revedge[i].v;
int w = revedge[i].w;
if(d[v] > d[u] + w)
{
d[v] = d[u] + w;
if(!vis[v])
{
q[t++] = v;
vis[v] = 1;
}
}
}
}
}
int Astar(int src, int des)
{
int cnt = 0;
priority_queue<A>Q;
if(src == des) k++;
if(d[src]==inf) return -1;
A t, tt;
t.v = src, t.g = 0, t.f = t.g + d[src];
Q.push(t);
while(!Q.empty())
{
tt = Q.top();
Q.pop();
if(tt.v == des)
{
cnt++;
if(cnt == k) return tt.g;
}
for(int i = head[tt.v]; i != -1; i = edge[i].next)
{
t.v = edge[i].v;
t.g = tt.g + edge[i].w;
t.f = t.g + d[t.v];
Q.push(t);
}
}
return -1;
}
int main()
{
scanf("%d%d%d", &n, &m,&k);
init();
scanf("%d%d", &s, &t);
for(int i = 1; i <= m; i++)
{
int x,y,w;
scanf("%d%d%d", &x, &y, &w);
insert(x, y, w);
}
spfa(t);
printf("%d\n", Astar(s, t));
}
Q - New N皇后问题2
题意:N皇后呗
回溯就好了,代码写的太丑了就不放出来了(>∧<)
剩下的题目,emmmm,要补也得一个月后了。
再不学习真的要挂科了
此时,2018/6/7 23:36,距离汇编语言考试还有3天,汇编语言学习进度1%
(๑→ܫ←)
滚去学习了……