题目一:子串模糊匹配
题目:
从字符串string开始完整匹配子串sub,返回匹配到的字符个数。
sub中如果出现'?'表示可以匹配一到三个除'\0'以外的任意字符。
如果sub还有找不到匹配的字符,则说明不能完整匹配。
如果能完整匹配,返回匹配到的字符个数,如果有多种匹配方式,返回匹配字符数最少的那个,如果不能完整匹配,返回-1
正则表达式:
let str = readline();
let key = readline();
let re = key.split("?");
re = "^"+re.join(".{1,3}?");
re = RegExp(re);
const res = re.exec(str);
console.log(res ? res[0].length : -1);
题目二:
题目:
有K种颜色的小球(K<=10),每种小球有若干个,总数小于100个。
现在有一个小盒子,能放N个小球(N<=8),现在要从这些小球里挑出N个小球,放满盒子。
想知道有哪些挑选方式。注:每种颜色的小球之间没有差别。
请按数字递增顺序输出挑选小球的所有方式。
如有3种颜色,每种颜色小球的个数分别为a:1,b:2,c:3,挑出3个小球的挑法有:
003,012,021,102,111,120
#include <iostream>
#include<vector>
#include<numeric>
using namespace std;
struct node{
int num;
vector<vector<int> > v;
};
int main(){
int K, N,Ki;
cin >> K >> N;
vector<node> ball(K);
for(int i=0;i<K;i++){
node p;
cin>>Ki;
ball[i].num=Ki;
}
if(K==1) cout<<N<<endl;
else {
vector<int> tmpv;
for(int i=0;i<=ball[0].num;i++) {
tmpv.push_back(i);
ball[0].v.push_back(tmpv);
tmpv.clear();
}
for(int i=1;i<K;i++){
for(int j=0;j<ball[i-1].v.size();j++){
for(int k=0;k<=ball[i].num;k++){
tmpv=ball[i-1].v[j];
tmpv.push_back(k);
if(i==K-1){
if(accumulate(tmpv.begin(),tmpv.end(),0)==N){
for(int l=0;l<tmpv.size();l++) cout<<tmpv[l];
cout<<endl;
}
}
else {
if(accumulate(tmpv.begin(),tmpv.end(),0)<=N) ball[i].v.push_back(tmpv);
}
tmpv.clear();
}
}
}
}
}
题目三:下棋
题目:
8x8的棋盘上,布有黑白两色棋子,白子先下,当白子下N手后,棋盘上最多有可能留下多少颗白子?
下法规则:
1.每次落子后,以该棋子为中心的8个方向(米字形的8条直线),如果有同色棋子,
且两个同色棋子之间连续排列着若干个异色棋子,无空白及同色棋子。则,这次落子可以把这些夹在中间的异色棋子全部翻色(即黑变白,白变黑)。
2. 黑白子交错落子。
3. 如果一个位置上有棋子,不能继续在该位置上落子;
4. 如果一个位置上落子后,不能翻对手的棋子,则该位置不能落子;
1表示黑色,2表示白色,0表示空白未落子
白棋落子后,棋盘变化情况如下所示:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 0 0 0 => 0 0 0 1 2 0 0 0
0 0 0 2 1 0 0 0 0 0 0 2 2 2 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 2 0 0 0 => 0 0 0 1 2 0 0 0
0 0 1 2 1 2 0 0 0 0 1 2 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#define ll long long
using namespace std;
typedef pair<int,int> p;
int mp[8][8];
int dir[8][2]={-1,0,1,0,0,-1,0,1,-1,-1,-1,1,1,-1,1,1};//上,下,左,右,左上,右上,左下,右下
int n,ans;
int find_sum(int x,int y,int dx,int dy,int nwcolor,int others)
{
int cnt=1;
x+=dx; y+=dy;
while(x>=0&&x<8&&y>=0&&y<8)
{
if(mp[x][y]==nwcolor)
return cnt;
if(mp[x][y]!=others)
return 0;
x+=dx;
y+=dy;
cnt++;
}
return 0;
}
void dfs(int step)
{
if(step==n)
{
int cnt=0;
for(int i=0; i<8; i++)
{
for(int j=0; j<8; j++)
if(mp[i][j]==2) cnt++;
}
ans=max(ans,cnt);
return;
}
int nw,lst;
vector<p> g;//保存要改变的棋子位置
if(step%2==0)
{
nw=2;
lst=1;
}
else
{
nw=1;
lst=2;
}
for(int i=0; i<8; i++)
{
for(int j=0; j<8; j++)
{
if(mp[i][j]==0)
{
int flag=0;//回溯标记
for(int k=0; k<8; k++)
{
int cnt=find_sum(i,j,dir[k][0],dir[k][1],nw,lst);//从当前位置[i,j]沿当前方向可以改变多少个棋子
if(cnt>1)
{
int x=i,y=j;
for(int ii=0; ii<cnt; ii++)
{
mp[x][y]=nw;
g.push_back(make_pair(x,y));//保存要更新的棋子位置
x+=dir[k][0];
y+=dir[k][1];
}
flag=1;
}
}
if(flag)
{
dfs(step+1);
for(int ii=0; ii<g.size(); ii++)//回溯
{
mp[g[ii].first][g[ii].second]=lst;
}
mp[i][j]=0;
g.clear();
}
}
}
}
}
int main()
{
scanf("%d",&n);
n=2*n-1;
for(int i=0; i<8; i++)
{
for(int j=0; j<8; j++)
{
scanf("%d",&mp[i][j]);
}
}
ans=0;
dfs(0);
printf("%d\n",ans);
return 0;
}
题目四:
题目: 一个长方体,长宽高分别为x,y,z,都为自然数。
现在要把若干个相同的长方体摆成高为N的一根柱形体。
每层摆1个,如果两种摆法的高度是一样的,则认为这两种摆法等价,所以每层只有三种摆法。
求一共有多少种摆法。
#include<iostream>
using namespace std;
int x,y,z;
int dp(int n,int l){
if(l>n)
return 0;
else{
if(l==n)
return 1;
return dp(n-l,x)+dp(n-l,y)+dp(n-l,z);
}
}
int main(){
int N;
cin>>N>>x>>y>>z;
int r=dp(N,x)+dp(N,y)+dp(N,z);
cout<<r;
return 0;
}
题目五:IP段合并
题目: 一个数字段由首尾两个数字标识,表示一个自然数集合,
比如数字段[beg, end)表示从beg到end之间的所有自然数,
包含beg,但不包含end。
有若干个数字段,这些数字段之间可能有重叠,
怎么把这些数字段合并去重,用最少个数的数字段来表示。
合并前后,整个集合包含的数字不发生变化。
import sys
if __name__ == '__main__':
N = int(sys.stdin.readline().strip())
raw_input = []
for line in sys.stdin:
raw_input.append(list(map(int, line.split())))
raw_input.sort(key=lambda x:x[0])
res = [raw_input[0]]
for value in raw_input:
if value[0] <= res[-1][1]:
res[-1][1] = max(res[-1][1], value[1])
else:
res.append(value)
for interval in res:
print('{} {}'.format(interval[0], interval[1]))
题目六:查找重复序列
题目: 已知某序列S=<e1,e2,…,en>,序列中的元素类型为整数(en <= 2^10),序列的长度为可变长度。
现在有若干序列S1,S2,…,Sn,现在要求设计一种算法,找出这些重复的序列。输出重复序列的序号,如果有多组重复,需全部输出。
所有序列中的数字个数加起来,小于1000000,序列个数小于10000个。
例如现有3个序列
S1=<65,43,177,655>
S2=<1,2,3,4,5,6,7>
S3=<65,43,177,655,3>
这时序列无重复。又如
S1=<65,43,177,655,3>
S2=<1,2,3,4,5,6,7>
S3=<65,43,177,655,3>
这时序列有重复。
from collections import OrderedDict
if __name__ == '__main__':
N = int(input())
res = OrderedDict()
for i in range(N):
input()
hash_code = hash(input())
if hash_code in res:
res[hash_code].append(i)
else:
res[hash_code] = [i]
is_find = False
for k, v in res.items():
if len(v) > 1:
is_find = True
print(*v)
if not is_find:
print('no')