hihocoder题目

#1014 : Trie树

思路:Trie树模板题

 1 #include<stdio.h>
 2 #include<string.h>
 3 
 4 typedef struct Trie
 5 {
 6   int count;
 7   struct Trie* next[26];
 8 }Trie_Node;
 9 
10 Trie_Node* creat()
11 {
12     Trie_Node* node = (Trie_Node*)malloc(sizeof(Trie_Node));
13     memset(node, 0, sizeof(node));
14     return node;
15 }
16 
17 void insert(Trie_Node* root, char* str)
18 {
19     Trie_Node* node = root;
20     char* s = str;
21     
22     while (*s)
23     {
24         if (node->next[*s - 'a'] == NULL)
25             node->next[*s - 'a'] = creat();
26         node = node->next[*s - 'a'];
27         node->count++;
28         s++;
29     }
30 }
31 
32 int search(Trie_Node* root, char* str)
33 {
34     Trie_Node* node = root;
35     char* s = str;
36     
37     while (*s)
38     {
39         node = node->next[*s - 'a'];
40         if (node == NULL)
41             return 0;
42         else
43             s++;
44     }
45     
46     return node->count;
47 }
48 
49 int main()
50 {
51     Trie_Node* root = creat();
52     char s[15];
53     int n, m;
54     
55     scanf("%d", &n);
56     while (n--)
57     {
58         scanf("%s", s);
59         insert(root, s);
60     }
61     
62     scanf("%d", &m);
63     while (m--)
64     {
65         scanf("%s", s);
66         printf("%d\n", search(root, s));
67     }
68     
69     return 0;
70 }
View Code:

#1015 : KMP算法

思路:kmp模板题

 1 #include <iostream>
 2 #include<string>
 3 
 4 using namespace std;
 5 
 6 void get_next(int* p, int n, string s)
 7 {
 8     int i = 0;
 9     int j = -1;
10     p[0] = -1;
11     
12     while (i < n)
13     {
14         if (j == -1 || s[i] == s[j])
15         {
16             i++;
17             j++;
18             p[i] = j;
19         }
20         else
21             j = p[j];
22     }
23 }
24 
25 int main()
26 {
27     int num;
28     string s;
29     string t;
30     int m, n;
31     int count;
32     
33     cin >> num;
34     while (num--)
35     {
36         count = 0;
37         cin >> s >> t;
38         m = s.size();
39         n = t.size();
40         
41         int* next = new int[m + 1];
42         get_next(next, m, s);
43         
44         int i = 0;
45         int j = 0;
46         while(i < n)
47         {
48             if (j == -1 || t[i] == s[j])
49             {
50                 i++;
51                 j++;
52             }
53             else
54                 j = next[j];
55             
56             if (j >= m)
57             {
58                 count++;
59                 j = next[j];
60             }
61         }
62         cout << count << endl;
63     }
64     
65     return 0;
66 }
View Code:

改进kmp

 1 #include <iostream>
 2 #include <vector>
 3 #include <string>
 4 
 5 using namespace std;
 6 
 7 void get_next(vector<int>& p, int n, string s)
 8 {
 9     int i = 0;
10     int j = -1;
11     p[0] = -1;
12     
13     while (i < n)
14     {
15         if (j == -1 || s[i] == s[j])
16         {
17             i++;
18             j++;
19             if (s[i] != s[j])
20                 p[i] = j;
21             else
22                 p[i] = p[j];
23         }
24         else
25             j = p[j];
26     }
27 }
28 
29 int main()
30 {
31     int num;
32     string s;
33     string t;
34     int m, n;
35     int count;
36     
37     cin >> num;
38     while (num--)
39     {
40         count = 0;
41         cin >> s >> t;
42         m = s.size();
43         n = t.size();
44         
45         vector<int> next(m + 1, 0);
46         get_next(next, m, s);
47         
48         int i = 0;
49         int j = 0;
50         while(i < n)
51         {
52             if (j == -1 || t[i] == s[j])
53             {
54                 i++;
55                 j++;
56             }
57             else
58                 j = next[j];
59             
60             if (j >= m)
61             {
62                 count++;
63                 j = next[j];
64             }
65         }
66         cout << count << endl;
67     }
68     
69     return 0;
70 }
View Code:

#1032 : 最长回文子串

思路:大名鼎鼎的Manacher算法,通过空间换时间,时间复杂度:O(n)

 1 #include <iostream>
 2 #include <string>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <vector>
 7 
 8 using namespace std;
 9 
10 char str[2000020],s[2000020];
11 
12 void solve()
13 {
14     int len = strlen(s);
15     string r;
16     r.resize(2 * len + 2);
17     r[0] = '$';
18     r[1] = '#';
19     for (int i = 0; i < len; ++i)
20     {
21         r[(i + 1) << 1] = s[i];
22         r[((i + 1) << 1) + 1] = '#';
23     }
24     
25     vector<int> p(r.size(), 0);
26     int max_len = 0;
27     int mm = 0;
28     int id = 0;
29     for (int i = 1; i < 2 * len + 2; i++)
30     {
31         if (mm > i)
32             p[i] = (mm - i < p[2 * id - i]) ? (mm - i) : (p[2 * id - i]);
33         else
34             p[i] = 1;
35 
36         while (r[i - p[i]] == r[i + p[i]])
37             p[i]++;
38 
39         if (i + p[i] > mm)
40         {
41             id = i;
42             mm = i + p[i];
43         }
44 
45         if (p[i] > max_len)
46             max_len = p[i];
47     }
48 
49     printf("%d\n", max_len - 1);
50 }
51 
52 int main()
53 {
54     int t;
55 
56     scanf("%d", &t);
57     while (t--)
58     {
59         scanf("%s", s);
60         solve();
61     }
62 
63     return 0;
64 }
View Code:

#1038 : 01背包

思路:01背包模板题

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     int n, m;
10 
11     cin >> n >> m;
12     vector<int> need(n);
13     vector<int> value(n);
14     vector<long long> dp(m + 1, 0);
15 
16     for (int i = 0; i < n; i++)
17         cin >> need[i] >> value[i];
18 
19     for (int i = 0; i < n; i++)
20     {
21         for (int j = m; j >= need[i]; j--)
22             dp[j] = max(dp[j], dp[j - need[i]] + value[i]);
23     }
24     cout << dp[m] << endl;
25     return 0;
26 }
View Code:

#1040 : 矩形判断

思路:首先判断是不是四个顶点,首先必须是四边形,用set判断,然后两组对边分别平行就是平行四边形,再加一组邻边相互垂直就是矩形了

坐标判断法:平行:x1*y2 - x2*y1 = 0  垂直:x1*x2 + y1*y2 = 0

因为只有四条边,所以直接搜了

 1 #include <iostream>
 2 #include <string>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <set>
 7 #include <vector>
 8 
 9 using namespace std;
10 
11 int main()
12 {
13     int n;
14     vector<long long> v(4);
15     pair<long long, long long> p[4];
16 
17     cin >> n;
18     for (int i = 0; i < n; i++)
19     {
20         int flag = 0;
21         int id = 0;
22         set<pair<long long, long long>> s;
23         vector<vector<long long>> line;
24 
25         for (int j = 0; j < 4; j++)
26         {
27             cin >> v[0] >> v[1] >> v[2] >> v[3];
28             line.push_back(v);
29             s.insert(make_pair(v[0], v[1]));
30             s.insert(make_pair(v[2], v[3]));
31         }
32         if (s.size() != 4)
33             cout << "NO" << endl;
34         else
35         {
36             p[0] = make_pair(line[0][2] - line[0][0], line[0][3] - line[0][1]);
37             p[1] = make_pair(line[1][2] - line[1][0], line[1][3] - line[1][1]);
38             p[2] = make_pair(line[2][2] - line[2][0], line[2][3] - line[2][1]);
39             p[3] = make_pair(line[3][2] - line[3][0], line[3][3] - line[3][1]);
40             for (int i = 1; i < 4; i++)
41             {
42                 if (p[0].first * p[i].second == p[0].second * p[i].first)
43                 {
44                     id = i;
45                     break;
46                 }
47             }
48             if (id > 0)
49             {
50                 if (id == 1)
51                 {
52                     if (p[2].first * p[3].second == p[2].second * p[3].first && p[0].first * p[2].first + p[0].second * p[2].second == 0)
53                         flag = 1;
54                 }
55                 else if (id == 2)
56                 {
57                     if (p[1].first * p[3].second == p[1].second * p[3].first && p[0].first * p[1].first + p[0].second * p[1].second == 0)
58                         flag = 1;
59                 }
60                 else
61                 {
62                     if (p[2].first * p[1].second == p[2].second * p[1].first && p[0].first * p[2].first + p[0].second * p[2].second == 0)
63                         flag = 1;
64                 }
65 
66                 if (flag)
67                     cout << "YES" << endl;
68                 else
69                     cout << "NO" << endl;
70             }
71             else
72                 cout << "NO" << endl;
73         }
74     }
75     return 0;
76 }
View Code:

刚开始因为是乘号所以用的long long,后来发现int也能过

 1 #include <iostream>
 2 #include <set>
 3 #include <vector>
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     int n;
10     vector<int> v(4);
11     pair<int, int> p[4];
12 
13     cin >> n;
14     for (int i = 0; i < n; i++)
15     {
16         int flag = 0;
17         int id = 0;
18         set<pair<int, int>> s;
19         vector<vector<int>> line;
20 
21         for (int j = 0; j < 4; j++)
22         {
23             cin >> v[0] >> v[1] >> v[2] >> v[3];
24             line.push_back(v);
25             s.insert(make_pair(v[0], v[1]));
26             s.insert(make_pair(v[2], v[3]));
27         }
28         if (s.size() != 4)
29             cout << "NO" << endl;
30         else
31         {
32             p[0] = make_pair(line[0][2] - line[0][0], line[0][3] - line[0][1]);
33             p[1] = make_pair(line[1][2] - line[1][0], line[1][3] - line[1][1]);
34             p[2] = make_pair(line[2][2] - line[2][0], line[2][3] - line[2][1]);
35             p[3] = make_pair(line[3][2] - line[3][0], line[3][3] - line[3][1]);
36             for (int i = 1; i < 4; i++)
37             {
38                 if (p[0].first * p[i].second == p[0].second * p[i].first)
39                 {
40                     for (int j = 1; j < 4; j++)
41                     {
42                         if (j == i)
43                             continue;
44 
45                         for (int k = 1; k < 4; k++)
46                         {
47                             if (k == j || k == i)
48                                 continue;
49 
50                             if (p[j].first * p[k].second == p[j].second * p[k].first && p[0].first * p[j].first + p[0].second * p[j].second == 0)
51                                 flag = 1;
52                         }
53                     }
54                 }
55             }
56             if (flag)
57                 cout << "YES" << endl;
58             else
59                 cout << "NO" << endl;
60         }
61     }
62     return 0;
63 }
View Code:

#1043 : 完全背包

思路:01背包每个背包只能用一次,所以从后往前扫不会影响前边的结果,完全背包每个背包可以无限次使用,所以从前往后扫使用任意次直到装满

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     int n, m;
10 
11     cin >> n >> m;
12     vector<int> need(n);
13     vector<int> value(n);
14     vector<long long> dp(m + 1, 0);
15 
16     for (int i = 0; i < n; i++)
17         cin >> need[i] >> value[i];
18 
19     for (int i = 0; i < n; i++)
20     {
21         for (int j = need[i]; j <= m; j++)
22             dp[j] = max(dp[j], dp[j - need[i]] + value[i]);
23     }
24     cout << dp[m] << endl;
25     return 0;
26 }
View Code:

#1068 : RMQ-ST算法

思路:RMQ:求区间最大/最小值,在线处理算法——ST算法

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 1000005;
10 int n, Q;
11 int rmq[N][20];
12 int nums[N];
13 int q[N][2];
14 
15 void RMQ_ST()
16 {
17     for (int i = 0; i < n; i++)
18         rmq[i][0] = nums[i];
19 
20     int lenj = (int)log2(n);
21     for (int j = 1; j <= lenj; j++)
22     {
23         for (int i = 0; i + (1 << j) - 1 < n; i++)
24             rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
25     }
26 }
27 
28 void query()
29 {
30     for (int i = 0; i < Q; i++)
31     {
32         int l = q[i][0] - 1;
33         int r = q[i][1] - 1;
34         int k = (int)log2(r - l + 1);
35         printf("%d\n", min(rmq[l][k], rmq[r - (1 << k) + 1][k]));
36     }
37 }
38 
39 int main()
40 {
41     scanf("%d", &n);
42     for (int i = 0; i < n; i++)
43         scanf("%d", &nums[i]);
44     scanf("%d", &Q);
45     for (int i = 0; i < Q; i++)
46         scanf("%d%d", &q[i][0], &q[i][1]);
47 
48     RMQ_ST();
49 
50     query();
51 
52     return 0;
53 }
View Code:

(id从1开始)

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 1000005;
10 int n, Q;
11 int rmq[N][20];
12 int nums[N];
13 int q[N][2];
14 
15 void RMQ_ST()
16 {
17     for (int i = 1; i <= n; i++)
18         rmq[i][0] = nums[i];
19 
20     int lenj = (int)log2(n);
21     for (int j = 1; j <= lenj; j++)
22     {
23         for (int i = 1; i + (1 << j) - 1 <= n; i++)
24             rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
25     }
26 }
27 
28 void query()
29 {
30     for (int i = 0; i < Q; i++)
31     {
32         int l = q[i][0];
33         int r = q[i][1];
34         int k = (int)log2(r - l + 1);
35         printf("%d\n", min(rmq[l][k], rmq[r - (1 << k) + 1][k]));
36     }
37 }
38 
39 int main()
40 {
41     scanf("%d", &n);
42     for (int i = 1; i <= n; i++)
43         scanf("%d", &nums[i]);
44     scanf("%d", &Q);
45     for (int i = 0; i < Q; i++)
46         scanf("%d%d", &q[i][0], &q[i][1]);
47 
48     RMQ_ST();
49 
50     query();
51 
52     return 0;
53 }
View Code:

#1070 : RMQ问题再临

思路:小数据直接暴力扫,大数据线段树

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 10005;
10 int nums[N];
11 int n, Q;
12 
13 int main()
14 {
15     int num;
16     int l, r;
17     
18     scanf("%d", &n);
19     for (int i = 1; i <= n; i++)
20         scanf("%d", &nums[i]);
21     scanf("%d", &Q);
22     for (int i = 0; i < Q; i++)
23     {
24         scanf("%d%d%d", &num, &l, &r);
25         int res = nums[l];
26         if (num == 0)
27         {
28             while (l <= r)
29             {
30                 res = min(res, nums[l++]);
31             }
32             printf("%d\n", res);
33         }
34         else
35         {
36             nums[l] = r;
37         }
38     }
39 
40     return 0;
41 }
View Code:

#1077 : RMQ问题再临-线段树

思路:线段树经典问题:单点修改,查询区间最值

(注意读取/输出数据时要用scanf和printf)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 #define N 1000005
 8 #define lson (id << 1)
 9 #define rson ((id << 1) | 1)
10 #define mid ((l + r) >> 1)
11 int n, q;
12 int tree[4 * N];
13 
14 void push_up(int id)
15 {
16     tree[id] = min(tree[lson], tree[rson]);
17 }
18 
19 void build(int id, int l, int r)
20 {
21     if (l == r)
22     {
23         scanf("%d", &tree[id]);
24         return ;
25     }
26 
27     build(lson, l, mid);
28     build(rson, mid + 1, r);
29     push_up(id);
30 }
31 
32 void ins(int id, int l, int r, int pos, int t)
33 {
34     if (l == r)
35     {
36         tree[id] = t;
37         return ;
38     }
39 
40     if (pos <= mid)
41         ins(lson, l, mid, pos, t);
42     else
43         ins(rson, mid + 1, r, pos, t);
44     push_up(id);
45 }
46 
47 int query(int id, int l, int r, int ql, int qr)
48 {
49     if (ql <= l && r <= qr)
50         return tree[id];
51 
52     int res = 99999999;
53     if (ql <= mid)
54         res = min(res, query(lson, l, mid, ql, qr));
55     if (mid + 1 <= qr)
56         res = min(res, query(rson, mid + 1, r, ql, qr));
57 
58     return res;
59 }
60 
61 int main()
62 {
63     int num;
64     int left, right;
65 
66     cin >> n;
67     build(1, 1, n);
68 
69     cin >> q;
70     for (int i = 0; i < q; i++)
71     {
72         scanf("%d%d%d", &num, &left, &right);
73 
74         if (num == 0)
75             printf("%d\n", query(1, 1, n, left, right));
76         else
77             ins(1, 1, n, left, right);
78     }
79     return 0;
80 }
View Code:

#1089 : 最短路径·二:Floyd算法

思路:Flyod算法,从i到j的最短距离可以根据从i出发,经过任意k个节点到达j的最短距离,此时按照01背包的想法得出递推式:dp[k][i][j] = min(dp[k - 1][i][j], dp[k - 1][i][k] + dp[k  - 1][k][j]) ,化简为:dp[i][j] = min(dp[i][k], dp[k][j])

(注意k一定要在外层循环)

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     int n, m;
10     int x, y, d;
11 
12     cin >> n >> m;
13     vector<vector<int>> dis(n + 1, vector<int>(n + 1, 99999999));
14     for (int i = 1; i <= n; i++)
15         dis[i][i] = 0;
16 
17     for (int i = 1; i <= m; i++)
18     {
19         cin >> x >> y >> d;
20         if (d < dis[x][y])
21         {
22             dis[y][x] = d;
23             dis[x][y] = d;
24         }
25     }
26 
27     for (int k = 1; k <= n; k++)
28     {
29         for (int i = 1; i <= n; i++)
30         {
31             for (int j = 1; j <= n; j++)
32                 dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
33         }
34     }
35     for (int i = 1; i <= n; i++)
36     {
37         for (int j = 1; j <= n; j++)
38         {
39             cout << dis[i][j] << " ";
40         }
41         cout << endl;
42     }
43     return 0;
44 }
View Code:

 

posted on 2017-05-22 17:55  dxy1993  阅读(175)  评论(0编辑  收藏  举报